Java

java8 - ZonedDateTime 을 이용한 날짜 변환

willbsoon 2020. 10. 19. 11:54

ZonedDateTime

ZonedDateTime 클래스는 타임존 또는 시차 개념이 필요한 날짜와 시간 정보를 나타내기 위해서 사용. public 생성자를 제공하지 않기 때문에 객체를 생성할 때는 now()나, of()와 같은 정적 메소드를 사용

ZonedDateTime nowSeoul = ZonedDateTime.now(ZoneId.of("Asia/Seoul"));
System.out.println("Now in Seoul is " + nowSeoul);

ZonedDateTime now = ZonedDateTime.now();
System.out.println("Now is " + now); // 시스템 zone id를 따라감

ZonedDateTime hanguelnal = ZonedDateTime.of(2020, 10, 9, 0, 0, 0, 0, ZoneId.of("Asia/Seoul"));
System.out.println("Hanguelnal is " + hanguelnal);

ZonedDateTime hanguelnal2 = Year.of(2020).atMonth(10).atDay(9).atTime(0, 0).atZone(ZoneId.of("Asia/Seoul"));
System.out.println("Hanguelnal is " + hanguelnal2);

 

ZonedDateTime = LocalDateTime + 타임존/시차

ZonedDateTime은 LocalDateTime에 타임존 또는 시차 개념이 추가되어 있음. 따라서 다음과 같이 ZonedDateTime은 LocalDateTime와 타임존이나 시차 개념을 더하거나 빼면서 상호 변환이 가능

LocalDate date = LocalDate.of(2020, 10, 9);
LocalTime time = LocalTime.of(0, 0);
LocalDateTime hanguelnal = LocalDateTime.of(date, time);
System.out.println("DateTime = " + hanguelnal);
System.out.println("Date = " + date);
System.out.println("Time = " + time);

// LocalDateTime to ZonedDateTime
ZonedDateTime zonedDateTime = ZonedDateTime.of(hanguelnal, ZoneId.of("Asia/Seoul"));
System.out.println("ZonedDateTime = " + zonedDateTime);
System.out.println("DateTime = " + zonedDateTime.toLocalDateTime());
System.out.println("Date = " + zonedDateTime.toLocalDate());
System.out.println("Time = " + zonedDateTime.toLocalTime());

 

 

ZoneId vs. ZoneOffset

ZoneId은 타임존, ZoneOffset은 시차. ZoneOffset는 UTC 기준으로 고정된 시간 차이를 양수나 음수로 나타내는 반면에 ZoneId는 이 시간 차이를 타임존 코드로 씀. 예를 들어 서울의 경우 타임존 코드는 Asia/Seoul이고 시차는 +0900

ZoneOffset seoulZoneOffset = ZoneOffset.of("+09:00");
System.out.println("+0900 Time = " + ZonedDateTime.now(seoulZoneOffset));
ZoneId seoulZoneId = ZoneId.of("Asia/Seoul");
System.out.println("Seoul Time = " + ZonedDateTime.now(seoulZoneId));

  Summer Time(일괄절약타임) -  여름에는 한 시간 더 일찍 시간이 가는 지역이 있음.

이런 도시를 대상으로 ZonedDateTime 객체를 만들 때는 ZoneId를 사용하는 편이 훨씬 유리함. 계절에 따라 변하는 시차를 알아서 처리해주기 때문.

 

 

다른 타임존/시차 적용

withZoneSameInstant() 메소드를 사용하면 ZonedDateTime에 다른 타임존이나 시차 적용가능. 아래는 2002년 월드컵 한국과 이탈리아 16강 경기의 서을 기준 시작 시간에 다른 도시의 타임존이나 다른 시차를 적용해봄

ZonedDateTime hanguelnal = Year.of(2020).atMonth(10).atDay(9).atTime(0, 0).atZone(ZoneId.of("Asia/Seoul"));
System.out.println("Hanguelnal =     " + hanguelnal);

ZonedDateTime hanguelnal_utc = hanguelnal.withZoneSameInstant(ZoneOffset.UTC);
ZonedDateTime hanguelnal_london = hanguelnal.withZoneSameInstant(ZoneId.of("Europe/London"));
ZonedDateTime hanguelnal_newYork = hanguelnal.withZoneSameInstant(ZoneOffset.of("-0400"));
ZonedDateTime hanguelnal_vancouver = hanguelnal.withZoneSameInstant(ZoneId.of("America/Vancouver"));

System.out.println("Hanguelnal_UTC =       " + hanguelnal_utc);
System.out.println("Hanguelnal_London =    " + hanguelnal_london);
System.out.println("Hanguelnal_NewYork =   " + hanguelnal_newYork);
System.out.println("Hanguelnal_Vancouver = " + hanguelnal_vancouver);

 

 

ZonedDateTime과 String 간 변환

ZonedDateTime의 format() 메소드에 DateTimeFormatter 객체를 넘기면 다양한 포멧의 문자열로 변환가능. DateTimeFormatter 클래스에서 정적 필드로 정의해 놓은 표준 포멧터, ofPattern(), ofLocalizedDateTime() 정적 메소드등을 사용해 변환 할 수 있음.

ZonedDateTime hanguelnal = Year.of(2020).atMonth(10).atDay(9).atTime(0, 0).atZone(ZoneId.of("Asia/Seoul"));

System.out.println(hanguelnal.format(DateTimeFormatter.ISO_DATE_TIME));
System.out.println(hanguelnal.format(DateTimeFormatter.ofPattern("yyyy/MM/dd/ HH:mm:ss z")));
System.out.println(hanguelnal.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL)));
System.out.println(hanguelnal.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withLocale(Locale.KOREA)));

반대로 문자열을 ZonedDateTime로 변환하기 위해서는 parse() 정적 메소드에 DateTimeFormatter 객체를 넘기면 됨.

아래는 모두 같은 케이스.

ZonedDateTime zdt1 = ZonedDateTime.parse("2020-10-09T00:00:00+09:00[Asia/Seoul]");
ZonedDateTime zdt2 = ZonedDateTime.parse("2020/10/09/ 00:00:00 KST", DateTimeFormatter.ofPattern("yyyy/MM/dd/ HH:mm:ss z"));
ZonedDateTime zdt3 = ZonedDateTime.parse("Friday, October 9, 2020 12:00:00 AM KST", DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL));
ZonedDateTime zdt4 = ZonedDateTime.parse("2020년 10월 9일 금요일 오전 12시 00분 00초 KST", DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withLocale(Locale.KOREA));

 

 

 

출처 : www.daleseo.com/java8-zoned-date-time/