본문 바로가기

Language/Java

Java - LocalDateTime, LocalDate 날짜 차이 구하기 (관련 이슈처리)

LocalDateTime

1. 문제 상황

App의 Server를 개발하던 중, 회원가입 부분을 구축하는 상황이었습니다. 회원가입시에는, 사용자의 출국날짜를 입력받게 되는데요, 이때 회원가입 진행 시간이 출국날짜 최소 하루 전이어야 하는 상황이었습니다.

 

날짜를 나타내는 데이터 타입의 경우 출국 시간까지를 표현하기 위해 LocalDateTime을 사용중이었고, 현재 일(Day)과 출국일(Day) 사이의 일수를 계산하기 위해 Duration 을 사용하였습니다.

 

이와 같은 상황에서 테스트를 거의 통과하는듯 싶었으나, 출국날짜를 회원가입이 가능한 최소 날짜인 내일로 지정하여 테스트를 하면 계속해서 도메인 제약사항에 걸려 Exception을 발생시켰습니다.

 

 

 

 

2. 원인 분석

원인을 찾기 위해 위와 같이 두 날짜의 일수 차이가 1일인 가상의 상황을 만들어 테스트를 진행해본 결과, 계속해서 날짜의 차이가 0이었습니다.

 

 

2.1 Duration.between() 분석

0이 발생하는지를 알아보기 위해 Duration의 between()메소드를 알아보아야 할 것 같습니다.

 

 

between(Temporal startInclusive, Temporal endExclusive)

우선 between 메소드는 Temporal타입의 데이터를 2개를 매개변수로 받아, Temporal타입 안에 존재하는 until()이라는 메소드를 이용하여 두 Temporal 사이의 차이를 계산하여 ofNanos()라는 메소드의 매개변수로 넘겨줍니다.

Temporal 타입의 구현체로는 LocalDateTime, LocalDate 등이 있습니다.

 

 

ofNanos(long nanos)

ofNanos 메소드의 경우 매개변수로 전달 받은 nanos를 sec로 변환하고 이를 Duration타입으로 변환하여 return합니다. 결과적으로 우리는 DurationtoDays() 메소드를 이용하여 두날짜 사이의 차이를 일(Day)로 변경하여 계산할 것입니다.

 

 

toDays()

toDays() 메소드의 경우에는 Duration의 초를 일수로 환산합니다.

 

 

 

2.2 원인

Duration의 between() 메소드는 날짜의 차이를 seconds(초)로 만들어 주고, 다시 toDays() 메소드를 이용해 seconds(초)를 일로 변환하는 것입니다. 따라서 두 날짜 사이의 차이를 초로 나타내었을때, 하루를 초로 변환한 86400초를 넘기지 않는다면 이는 1일로 계산이 되지 않습니다.

 

 

다시한번 말씀드리면, LocalDateTime의 경우 계산시, 하루의 1초만 지나더라도 이를 toDays() 메소드를 이용해 일로 변환시 0일로 계산이됩니다.

 

 

 

 

3. 해결방법

저는 이를 해결하기 위해, 시간을 고려하지 않는 타입인 LocalDate형으로 변환하여 계산을 하도록 만들었습니다.

 

 

Exception in thread "main" java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Seconds 에러

하지만, LocalDate를 곧이 곧대로 이용해 두 날짜사이의 일수를 계산하려 한다면, 위와 같은 에러가 발생합니다. LocalDate를 지원하지 않기 때문입니다. 예측하건데, LocalDate 에는 년,월,일이 존재하지만 시간이 존재하지 않기 때문에 이를 계산할 수 없기 때문인것 같습니다.

 

하지만 다행이도 LocalDate에는 atStartOfDay()라는 메소드가 존재합니다. 이 메소드는 LocalDate년,월,일을 그대로 사용하고, 시간은 하루의 시작이자 끝시간으로 맞추어, LocalDateTime으로 반환해주는 역할을 합니다.

 

 

성공입니다.