웹 개발

Java에서 날짜, 시간 제대로 사용하기(LocalDate, LocalTime, LocalDateTime)

노루아부지 2020. 9. 22. 09:24

1. 사용하지 않는 게 좋은 Calendar, Date 클래스

 

Java를 처음 공부할 때나 단순하게 표현할 때는 Calendar, Date 클래스를 사용할 수 있지만, 문제가 많은 클래스 이기 때문에 실무에서는 사용하지 않는 게 좋습니다.

이런 이유로 많은 개발자들이 Joda-Time 같은 오픈소스 라이브러리를 사용했는데 JDK 8부터는 개선된 날짜/시간 API가 제공됩니다.

 

 

2. Calendar, Date 클래스의 문제점

 

1) 불변 객체가 아니다.

Calendar와 Date 클래스에서 set 메서드를 호출해서 날짜를 저장하면 연산 결과는 같은 인스턴스에 저장됩니다. 이 때문에 Calendar 객체나 Date 객체가 여러 객체에서 공유되면 한 곳에서 바꾼 값이 다른 곳에 영향을 미치는 부작용이 생길 수 있습니다.

또한, 같은 원인으로 악의적으로 변경될 수 있습니다.

 

2) int 상수 필드의 남용

Calendar를 사용한 날짜 연산은 아래와 같이 int 상수 필드를 사용합니다.

calendar.add(Calendar.SECOND, 1);

첫번째 파라미터에 Calendar.JUNE과 같이 전혀 엉뚱한 값이 들어가도 이를 컴파일 시점에서 확인할 방법이 없습니다.

 

 

3) 헷갈리는 월(month) 지정

10월에 해당하는 Calendar.OCTOBER의 실제 값은 9입니다. 따라서 Calendar 상수를 사용하지 않고 상수를 사용하는 개발자들은 다음과 같은 실수를 반복하고 있습니다. 또한 13월과 같이 잘못된 월을 설정해도 오류가 발생하지 않습니다.

calendar.set(2020, 10, 4);

 

4) 일관성 없는 요일 상수

Calendar.get(Calendar.DAY_OF_WEEK)에서 반환한 요일은 일요일이 1입니다. 그런데 calendar.getTime() 메서드로 Date 객체를 얻어와서 Date.getDay() 메서드로 요일을 구하면 일요일이 0입니다. 두 개의 클래스 사이에 요일 지정 값이 맞지 않습니다.

 

 

5) Date와 Calendar의 불편한 역할 분담

Date자료형으로 변수를 생성하더라도 Date로 날짜 계산이 어려움이 있기 때문에 보통 Calendar 객체를 생성하고, 날짜 계산을 한 후 다시 Date 객체를 리턴해야 하는 문제가 있습니다.

이런 이유로, 날짜를 계산하기 위해서는 별도의 메서드를 개발해서 호출해야 했습니다.

 

 

6) 에러를 발생 시키지 않는 시간대 ID 설정

TimeZone 설정 시, Asia/Seoul 대신 Seoul/Asia로 잘못 지정해도 에러를 발생시키지 않기 때문에 찾기 어려운 버그가 생길 수 있습니다.

 

 

3. Java의 새로운 날짜 API(LocalDate, LocalTime, LocalDateTime)​

 

LocalDate, LocalTime, LocalDateTime 클래스는 객체를 생성하기 위해서 now()와 of()라는 메서드를 제공합니다.

now() 메서드는 현재의 날짜와 시간을 이용하여 새로운 객체를 생성하여 반환합니다.

of() 메서드는 전달된 인수를 가지고 특정 날짜와 시간을 표현하는 새로운 객체를 생성하여 반환합니다.

 

새로운 API의 특징(장점)은 다음과 같습니다.

  • Calendar, Date를 혼용해서 사용하던 전과 달리 LocalDate만 사용하기 때문에 잘못 지정하거나 혼동할 여지가 없다.
  • 생성자 대신 of() 메서드 같은 static factory 메서드를 많이 사용한다. DateTimeFormatter.ofPattern(), Instant.from() 등이 그 예이다. static factory 메서드는 가독성 있는 이름을 따로 붙일 수 있고, 생성자와는 달리 한번 생성된 객체를 재활용할 수도 있다.
  • 13월 같이 잘못된 월이 설정되면 IllegalFieldValueException가 발생
  • 잘못된 TimeZone 설정에는 IllegalArguementException 가 발생
  • 직관적인 날짜 계산 ( plusDays() 메서드 등)
  • 기존 Calendar, Date 시간 클래스가 밀리초(millisecond) 단위의 정밀성을 가졌던 반면, 새로운 클래스는 나노초까지 다룰 수 있다.

LocalDate, LocalTime, LocalDateTime을 JDK7에서 사용할 수 있는 모듈도 존재합니다.

 

pom.xml에 다음과 같이 의존성을 추가하면 사용할 수 있습니다.

<dependency>  
    <groupId>org.threeten</groupId> 
    <artifactId>threetenbp</artifactId> 
    <version>0.8.1</version> 
</dependency>  

 

4. LocalDate, LocalTime, LocalDateTime 사용법

// 1일 후 구하기
LocalDate dt1 = LocalDateTime.now().plusDays(1);

// 1시간 후 구하기
LocalDate dt2 = LocalDateTime.now().plusHours(1);

// 1999년 12월 31일을 지정
LocalDate dt3 = LocalDate.of(1999, 12, 31);

// 시분초를 00:00:00으로 설정 (Set time to 00:00:00)
LocalDateTime dateTime = LocalDateTime.now();
LocalDateTime day3 = dateTime.truncatedTo(ChronoUnit.DAYS);

// 오늘 오전 6시
LocalDateTime todayAt6 = LocalDate.now().atTime(6, 0);

// LocalDateTime 값을 yyyyMMdd 포멧으로 변경
// LocalDate로 하면 오류 발생
String formatDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));

 

 

[참고 사이트]

https://d2.naver.com/helloworld/645609

http://tcpschool.com/java/java_time_localDateTime

728x90
loading