반응형

환경: springboot2.7.6. java11,  mysql5.7

 

문제 상황

endDate에 23:59:59를 세팅하는 게 귀찮고 반복적이라 느껴져서 LocalTime.MAX를 사용하는 방향으로 구현하고 있었다.

private LocalDateTime endDate;

//
endDate.toLocalDate().atTime(LocalTime.MAX) 
//위와 동일
endDate.withHour(23).withMinute(59).withSecond(59).withNano(999999999)

 

디버그 시 endDate에 23:59:59:99999.. 로 잘 들어가는 것을 확인하고 entity.save를 진행하였는데

디비에 들어가는 값은 그 다음날 00:00:00으로 들어가 있었다.

즉 2024-01-01 23:59:59.9999999.. 로 저장을 해도 디비에는 2024-01-02 00:00:00으로 들어가는 상황

 

원인

java단에서 오류가 아님을 확인하니 mysql 단에서 자체 처리하는 것이라는 생각이 들었다.

LocalTime.MAX는 초 이하 9자리까지 지원한다.

즉, 23:59:59.999999999 로 처리한다.

 

현재 해당 디비 콜롬은 아래처럼 정의되어 있다.

초 단위 미만을 지원하지 않는 datetime은 초 단위 아래 값이 오면 반올림해버린다.

하여 초 단위 보다 더 정밀한 시간 값이 필요하면 MySQL5.7에 추가된 fractional second를 이용한 datetime(6) 등을 사용해야 한다.

하지만 MySQL이 지원하는 Fractional Seconds의 최대 자릿수는 6자리고 이를 초과했기 때문에 LocalTime.MAX를 담으면 자동으로 반올림 처리된다.

 

https://lenditkr.github.io/MySQL/fractional-seconds-rouding-problem/

 

아니 시간도 반올림이 된다고?

니가 지정한 내가 아냐~ - Soo

lenditkr.github.io

 

그리고 JPA/mysql-connector 내부적으로도 반올림하는 부분이 있어 시간에 민감한 데이터인 경우 LocalDateTime.now()를 사용하는 것도 문제가 될 수 있다고 한다. 이럴 땐 DB connect 시 설정에 sendFractionalSeconds=false를 추가해줘야 하는 듯.

https://medium.com/naverfinancial/%EC%98%A4%EB%8A%98%EC%9E%90-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC-%EC%A1%B0%ED%9A%8C%ED%96%88%EB%8A%94%EB%8D%B0-%EB%8B%A4%EC%9D%8C%EB%82%A0-%EB%8D%B0%EC%9D%B4%ED%84%B0%EA%B0%80-%EB%94%B8%EB%A0%A4%EC%99%80%EC%9A%94-mysql-ae9b0f696742

 

오늘자 데이터를 조회했는데 다음날 데이터가 딸려와요 (MySQL)

안녕하세요. 네이버 파이낸셜 내자산&증권개발팀의 이정빈입니다.

medium.com

그래서

  • 날짜 저장 시 mysql의 콜롬 타입을 고려해야 하며
  • LocalTime.MAX 대신 LocalTime.of(23, 59, 59) / LocalTime.of(23, 59, 59, 999_999) 등으로 써야 한다..

 

728x90
반응형

+ Recent posts