티스토리 뷰

Java/Java8

[Java8] Date와 Time API

Xion 2020. 8. 1. 19:37

프로젝트를 진행하면서 시간과 날짜를 계산하는 일이 굉장히 많았다.

하지만 그 과정에서 헷갈린 부분을 정리하고 확실한 개념을 짚고 넘어가보고자 글을 정리한다.


| Date & Time 소개

 

java8에 새로운 날짜와 시간 API가 생긴 이유

  • 그전까지 사용하던 java.util.Date 클래스는 mutable(변하기 쉬운) 하기 때문에 thread safe 하지 않았다.
  • 클래스 이름이 명확하지 않다 ( Date인데 시간까지 다루는 점에 대해 의아했음 )
  • 버그가 발생하는 일이 많았다 ( type의 안정성이 없고 월 같은 경우 0부터 시작하는게 이해가 안돼..)
  • 날짜 시간 처리가 복잡한 application에서는 보통 Joda Time을 쓰곤 했다.

 

하지만 !!


java8 에서 제공하는 Date-Time API JSR-310 스펙의 구현체를 제공한다.

https://jcp.org/en/jsr/detail?id=310

 

주요 API

1. 기계용 시간(machine time)과 인류용 시간으로 나눌 수 있다.

2. 기계용 시간은 EPOCK(1970년 1월1일 0시0분0초)부터 현재까지의 TimeStamp를 표현한다.

3. 인류용 시간은 우리가 흔히 사용하는 연,월,일,시,분,초 등을 표현한다.

4. TimeStampInstant를 사용한다.

5. 특정 날짜(LocalDate), 시간(LocalTime), 일시(LocalDateTime)을 사용할 수 있다.

6. 기간을 표현할 때는 Duration(시간 기반)과 Period(날짜 기반)를 사용할 수 있다.

7. DateTimeFormatter를 사용해서 일시를 특정한 문자열로 포매팅할 수 있다.

 

 

| instant 활용

예시 ( 시간을 재거나 method 실행 시간을 측정할 때 사용  (기계용) )

 Instant instant = Instant.now();
 System.out.println(instant);
        
 ZoneId zone = ZoneId.systemDefault();
 System.out.println(zone);
        
 ZonedDateTime zonedDateTime = instant.atZone(zone);
 System.out.println(zonedDateTime);

 

| LocalDateTime 

인간용

서버에 배포가 되면 서버가 실행되는 국가에 따라서 시간이 auto setting 되기 때문에 주의한다.

 

method

  • of(int Month, int,int,int,int)

-> of를 사용하여 년,월,일,시를 설정할 수 있다.

  • now()

->현재 시스템 Zone에 해당하는 (로컬) 일시를 return한다.

  • ZonedDateTime.of(int Month,int,int,int,int,ZoneId)

->특정 Zone의 특정 일시를 return한다.

 

| 기간을 표현하는 방법 (Period 와 Duration)

  • Period / Duration.between() 

->인간용 비교

Period between = Period.between(today,birthDay);
System.out.println(between.get(ChronoUnit.DAYS));

Period 생일을 활용한 예시

		 LocalDate today = LocalDate.now();
         LocalDate myBirthDay = LocalDate.of(2020, Month.AUGUST, 23); //생일 setting 
         
         
         //case 1 between()을 활용한 예시
         Period period = Period.between(today, myBirthDay);
         System.out.println(period.getDays());
         
         //case 2 until()을 활용한 예시
         Period until = today.until(myBirthDay);
         System.out.println(until.getDays());

->Period 객체를 생성 후 between() OR until() & getDays() 를 활용하여 날짜가 얼마나 남은지 계산할 수 있다.

 

  • Duration 

->기계용 비교

  //기계용 ( 메서드 시간 측정 등 ) 
Instant now2 = Instant.now();
//현재 초 부터 10초 차이가 나도록 더해줌
Instant plus = now2.plus(10,ChronoUnit.SECONDS);
Duration between = Duration.between(now2, plus);
         
System.out.println(between.getSeconds());

//결과
10

 

 

| 문자열 입력 OR 출력

//format
LocalDateTime now3 = LocalDateTime.now();
DateTimeFormatter  MMddyyyy = DateTimeFormatter.ofPattern("yyyy/MM/dd");
System.out.println(now3.format(MMddyyyy));

//결과
2020/08/01

custom하게 pattern을 설정해줄 경우 LocalDateTime 으로 ofPattern() 메서드에 출력하고자 하는 형식을 지정해주고

LocalDateTime 객체의 format() 메서드를 호출하면 된다.

 

참고 Doc

 

| 사용자 입력 값(문자열) 파싱

  • parse

사용자가 원하는 형태인 날짜 형식으로 값을 뽑아내고 싶다면 parse 를 사용하여 파싱한다.

 //parse
//사용자가 문자열로 입력 값을 입력하면 -> 원하는 형식을 지정해주면 파싱되어 출력해준다.
DateTimeFormatter MMddyyyy2 = DateTimeFormatter.ofPattern("yyyy/MM/dd");
LocalDate parse = LocalDate.parse("1993/08/23",MMddyyyy2);
System.out.println(parse);

//결과
1993-08-23 // 문자열을 날짜 형식으로 출력한다

 

| Date & Instant Type Change 호환성 레거시 API 지원

 

//Date와의 호환성
Date date = new Date();		//date 객체 생성
         
Instant instant3 = date.toInstant();  //date객체를 Instant로 전환
         
Date newDate = Date.from(instant3);   // Instant객체를 from() 메서드를 활용하여 Date객체로 전환
         

-> Date 객체와 Instant 객체는 서로 호환되어 타입을 바꿀 수 있다.

 

또한

  • GregorianCalendar와 Date 타입의 인스턴스를 Instant나 ZonedDateTime으로 변환 가능.

  • java.util.TimeZone에서 java.time.ZoneId로 상호 변환 가능하다.

ZoneId newZoneAPI = TimeZone.getTimeZone("PST").toZoneId();
TimeZone legacyZoneAPI = TimeZone.getTimeZone(newZoneAPI);