airbnb 이면 외국 시간도 고려해야 되지 않을까요? KST 만 보는 것으로 합의되었다면 괜찮긴 합니다.
라는 리뷰가 보여서 시간선에 대해서 공부해봤다.
기존 java의 날씨 api에는 여러 문제가 있었다고 한다.
(Date, Calendar, SimpleDateFormat 클래스)
1)부적절한 클래스와 메서드 이름
Date 클래스의 경우, TimeStamp 방식으로 동작하고 시간을 내재하고 있으나, ClassName은 Date다.
2)Thread saftety 하지 않다.
ate 클래스의 경우 mutable 하기 때문에 다른 Thread에서 값을 참조하고 변경할 수 있다.
3) 버그가 발생할 여지가 많다.
Calendar 클래스의 경우 입력값의 month가 0이 1월로 처리된다. 그래서 Calendar.SEPTEMBER 같은 상수를 사용해야 하며, DB 데이터랑 연결하면서 서로 다르게 해석된다.


1970년 1월 1일 UTC의 첫 번째 순간 이후의 현재 시간까지의 나노초를 나타낸 값이다. 라이브러리는 epochSecond와 nanos로 나누어진다.
일반적으로 순간을 표현할 때 사용하며, Unix Timestamp를 구할 때 사용할 수 있다. Unix Timestamp를 사용하는 이유는 숫자 자료형을 가지고 연산을 하기 때문에 Local/Offset/ZonedDateTime과 비교했을 때 연산 속도가 훨씬 빠르다.
대부분의 비즈니스 로직, 데이터 저장 및 데이터 변경은 UTC로 이루어져야 하므로 자주 사용하기에 편리한 클래스라고한다.
Instant cur = Instant.now();
System.out.println(cur); // 2022-10-09T12:45:11.825755Z
System.out.println(cur.getEpochSecond()); // 1665319511
System.out.println(cur.getNano()); // 825755000
Instant의 now에서는 UTC 표준 시간대를 사용합니다. (Clock.systemUTC().instant())

Java Time에서 Local 이 들어가면 시간대(Zone Offset/Zone Region)에 대한 정보가 없다를 의미한다고 한다.
일반적으로 Local 클래스는 생일이나 기념일 등에 주로 사용된다.
LocalDate localDate = LocalDate.now();
System.out.println(localDate); // 2022-10-09
LocalTime localTime = LocalTime.now();
System.out.println(localTime); // 21:49:19.858512
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime); // 2022-10-09T21:49:19.858589
LocalDateTime의 now는 default time-zone의 정보를 사용한다. 내부적으로는 Instant형으로 바꾼 후, ZoneOffset으로 한번 바꾼 뒤 EpochSecond로 바꾼 이후에야 LocalDateTime으로 표현된다.
OffsetDateTime은 LocalDateTime + ZoneOffset 의 개념이다. OffsetDateTime는 UTC보다 몇 시간/분/초 앞 또는 뒤의 컨텍스트를 사용하여 순간을 날짜 및 시간으로 나타낸다.
System.out.println(OffsetDateTime.of(2000, 1, 1, 11, 11, 11, 0, ZoneOffset.UTC);
// 2000-01-01T11:11:11Z
System.out.println(OffsetDateTime.of(2000, 1, 1, 11, 11, 11, 0, ZoneOffset.of("+9"));
// 2000-01-01T11:11:11+09:00
// 위 두 값은 다르다.
ZonedDateTime은 OffsetDateTime + ZoneRegion 의 개념이다.OffsetDateTime 과의 차이점은 DST(Daylight Saving Time)와 같은 Time Transition Rule을 포함하는 ZoneRegion의 유무 차이다.
몇 개의 나라의 경우, 서머타임을 적용하기 때문에 때로는 겨울, 여름을 다르게 써야 하는데, 이를 자바에서는 하나의 Time Zone으로 통일하고, Time Transition Rule을 가지는 ZoneRules을 통해 알아서 내부적으로 계산해준다.
ZoneId seoulZoneId = ZoneId.of("Asia/Seoul");
System.out.println(seoulZoneId.getRules());
// ZoneRules[currentStandardOffset=+09:00]
System.out.println(seoulZoneId.getId());
// Asia/Seoul
System.out.println(ZonedDateTime.of(LocalDateTime.of(2020, 1, 1, 11, 11, 11, 0), ZoneId.of("Asia/Seoul")));
// 2020-01-01T11:11:11+09:00[Asia/Seoul]
System.out.println(ZonedDateTime.of(LocalDateTime.of(2020, 1, 1, 11, 11, 11, 0), ZoneId.of("Asia/Tokyo")));
// 2020-01-01T11:11:11+09:00[Asia/Tokyo]
// 위 두값은 다른 region이라 다르다.
// cet 는 유럽 시간
System.out.println(ZonedDateTime.of(2020, 1, 1, 11, 11, 11, 0, ZoneId.of("CET")));
// 2020-01-01T11:11:11+01:00[CET]
System.out.println(ZonedDateTime.of(2020, 6, 1, 11, 11, 11, 0, ZoneId.of("CET")));
// 2020-06-01T11:11:11+02:00[CET]
서머타임(daylight saving time)에 대해 코드와 함께 알아보자
[서머타임 시작]
America/New_York TimeZone에서 2022년 03월 13일 02:00:00 이 서머타임 시작 시각이라ㅗ 한다.
그 전후를 출력하면
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime eventStartDateTime = LocalDateTime.parse("2022-03-13 01:50:00", formatter);
ZonedDateTime eventStartZonedDateTime = ZonedDateTime.of(eventStartDateTime, ZoneId.of("America/New_York"));
for (int i=0; i<80; i++) {
eventStartZonedDateTime = eventStartZonedDateTime.plusMinutes(1);
System.out.println(eventStartZonedDateTime);
}

이 코드를 실행하면 중간에 갑자기 시차가 4시간 차이로 변경이 된다.
이는 서머타임으로 미국의 시간이 1시간 늦춰졌기 때문이다.
public static void main(String[] args) throws IOException {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime eventStartDateTime = LocalDateTime.parse("2022-11-06 01:00:00", formatter);
ZonedDateTime eventStartZonedDateTime = ZonedDateTime.of(eventStartDateTime, ZoneId.of("America/New_York"));
for (int i=0; i<130; i++) {
eventStartZonedDateTime = eventStartZonedDateTime.plusMinutes(1);
System.out.println(eventStartZonedDateTime);
}
}
서머타임이 종료되는 시간을 봐보자.

여기선 갑자기 시간이 1시간 앞당겨져서 4시간의 시차가 5시간으로 변경됐다.
국내에서만 서비스를 한다면 문제가 없을 것이다.
다만, 서머타임이 적용되는 해외에서 서비스를 할 때는 이러한 시간의 변경 문제로 버그가 발생할 수 있다고 한다.