Java 8 버전의 변경사항 중 하나는 java.time 패키지가 추가되었다는 것이다.
Date와 Calendar가 가진 아래와 같은 단점들을 해소하기 위함이었다.
Calendar 인스턴스는 불변 객체(immutable object)가 아니라서 값이 수정될 수 있음.
윤초(leap second)와 같은 특별한 상황을 고려하지 않음.
Calendar 클래스에서는 월(month)을 나타낼 때 1월부터 12월을 0부터 11까지로 표현해야 하는 불편함.
java.time 패키지에 속한 클래스들의 가장 큰 특징은 String 클래스 처럼 불변이라는 점이다. 그래서 날짜나 시간을 변경하는 메서드들은 항상 변경된 새로운 객체를 반환한다. (그래서 변경후에는 대입 연산자를 사용해주어야 한다!) 기존의 Date의 Calendar 클래스는 변경이 가능했기에 멀티스레드 환경에서 안전하지 못했다.
멀티스레드 환경에서는 동시에 여러 쓰레드가 같은 객체에 접근할 수 있기에 변경 가능한 객체는 데이터가 잘못된 가능성이 있으며, 이는 쓰레드에 안전(thread-safe)하지 못하다.
Instant 클래스는 EPOCH부터 경과된 시간을 나노초 단위로 표현한다. 단일 진법으로만 다루기에 계산이 쉽다.
Instant는 항상 UTC(+00:00)을 기준으로 하기 때문에, LocalTime과는 차이가 있을 수 있다. 우리나라의 경우에는 시간대가 '+09:00'이므로 Instant와 LocalTime간에는 9시간의 차이가 있다.
UTC(Coordinated Universal Time, 세계 협정시)는 1972년 1월 1일부터 시행된 국제 표준시이다.
Instant를 생성할 때는 아래와 같이 now()와 ofEpochSecond()를 사용한다.
import java.time.Instant;
public class InstantEx1 {
Instant now = Instant.now();
Instant now2 = Instant.ofEpochSecond(now.getEpochSecond());
Instant now3 = Instant.ofEpochSecond(now.getEpochSecond(), now.getNano());
}
LocalDateTime은 로컬 PC의 시스템 날짜와 시간을 반환한다.
import java.time.*;
public class LocalDateTimeEx1 {
public static void main(String[] args) {
LocalDate localDate = LocalDate.now();
System.out.println("localDate = " + localDate);
// localDate = 2022-02-20
LocalTime localTime = LocalTime.now();
System.out.println("localTime = " + localTime);
// localTime = 15:56:51.294833
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("localDateTime = " + localDateTime);
// localDateTime = 2022-02-20T15:56:51.295105
}
}
LocalDateTime에 시간대를 추가하면 ZoneDateTime이 된다. 새로운 패키지에서는 ZoneId라는 클래스를 사용하는데 ZoneId는 일괄 절약 시간(Daylight Saving Time)을 자동적으로 처리해주어 더 편하다. (사용 가능한 ZoneId 목록은 ZoneId.getAvailableZoneIds()로 얻을 수 있음)
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class ZoneIdEx1 {
public static void main(String[] args) {
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("localDateTime = " + localDateTime);
// localDateTime = 2022-02-20T16:00:26.857433
ZoneId zid = ZoneId.of("Asia/Seoul");
ZonedDateTime zdt = localDateTime.atZone(zid);
System.out.println("ZonedDateTime = " + zdt);
// ZonedDateTime = 2022-02-20T16:00:26.857433+09:00[Asia/Seoul]
}
}
만약 현재 특정 시간대의 시간, 예를 들어 뉴욕 시간을 알고 싶으면 다음과 같이 하면 된다.
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class ZoneIdEx2 {
public static void main(String[] args) {
ZoneId nyId = ZoneId.of("America/New_York");
ZonedDateTime nyTime = ZonedDateTime.now().withZoneSameInstant(nyId);
System.out.println("nyTime = " + nyTime);
// nyTime = 2022-02-20T02:06:55.886850-05:00[America/New_York]
ZoneId seoulId = ZoneId.of("Asia/Seoul");
ZonedDateTime seoulTime = ZonedDateTime.now().withZoneSameInstant(seoulId);
System.out.println("seoulTime = " + seoulTime);
// seoulTime = 2022-02-20T16:06:55.930719+09:00[Asia/Seoul]
}
}