Logo

[Java8 Time API] Instant 사용법

자바8 Time API의 Instant 클래스는 시간을 타임스탬프로 다루기 위해서 사용합니다. 타임스탬프는 UTC 기준으로 1970년 1월 1일 0시 0분 0초를 숫자 0으로 정하고 그로 부터 경과된 시간을 양수 또는 음수로 표현합니다. 타임스탬프는 인간에게는 직관적이지 않은 시간의 표현 방법이지만 고전적으로 기계에게는 매우 친화적인 방법으로 현재까지 널리 사용되어 왔습니다. 일단 시간을 표현하기 위해서 별도의 타입없이 기본 데이터 타입으로 표현이 가능한데다가, 타임존이 UTC로 고정되어 있기 때문에 타임스탬프가 어느 타임존 기준인지를 고려할 필요가 없기 때문입니다.

타임스탬프를 Instant로 나타내기

UTC 기준시인 1970년 1월 1일 0시 0분 0초에 해당하는 Instant 객체는 Instant.EPOCH라는 정적 필드에 저장되어 있습니다. 그리고 Instant.ofEpochSecond() 정적 메소드를 통해서 타임스탬프를 나타내는 Instant 객체를 만들 수 있습니다.

Instant epoch = Instant.EPOCH; // Instant.ofEpochSecond(0); 와 동일
System.out.println("epoch = " + epoch);

Instant epochInFuture = Instant.ofEpochSecond(1_000_000_000);
System.out.println("epochInFuture = " + epochInFuture);

Instant epochInPast = Instant.ofEpochSecond(-1_000_000_000);
System.out.println("epochInPast = " + epochInPast);
epoch = 1970-01-01T00:00:00Z
epochInFuture = 2001-09-09T01:46:40Z
epochInPast = 1938-04-24T22:13:20Z

위 출력 결과를 통해 타임스탬프의 1,000,000,000 값은 UTC 기준으로 2001년 9월 9일 1시 46분 40초에 해당함을 알 수 있습니다. 반대로 -1,000,000,000 값은 UTC 기준으로 1938년 4월 24일 22시 13분 20초에 해당함을 알 수 있습니다. 이와 같이 타임스탬프 값은 사람이 눈으로만 봤을 때는 계산기 없이는 바로 시간을 파악하기가 어렵기 때문에 Instant 객체로 변환해서 다루면 편리합니다.

현재 시간의 타임스탬프 값을 구하기

Instant.now() 정적 메소드를 호출하면 현재 시간의 Instant 객체를 얻을 수 있습니다. Instant 객체는 UTC 기준의 ISO 포맷으로 출력됩니다. 그리고 Instant 객체에 getEpochSecond()toEpochMilli() 메소드를 호출하여 초단위 또는 밀리 초 단위 타임스탬프 값을 long 타입으로 얻을 수 있습니다.

Instant current = Instant.now();
System.out.println("Current Instant = "+ current);

long epochSecond = current.getEpochSecond();
System.out.println("Current Timestamp in seconds = " + epochSecond);

long epochMilli = current.toEpochMilli();
System.out.println("Current Timestamp in milli seconds = " + epochMilli);
Current Instant = 2017-12-22T08:30:18.870Z
Current Timestamp in seconds = 1513931481
Current Timestamp in milli seconds = 1513931418870

Instant와 ZonedDateTime 간 상호 변환하기

Instant 클래스의 atZone() 메서드와 ZonedDateTime 클래스의 toInstnat() 메소드를 통해서 두 타입의 객체는 서로 변환이 가능합니다. 예를 들어 2002년 월드컵 한국과 이탈리아의 16강 경기는 한국 시간으로 6월 18일 20시 30분에 치뤄졌으며 이를 서울 타임존의 ZonedDateTime 객체로 나타낼 수 있습니다. 이를 Instant 객체로 변환하면 UTC 기준 시간이 되기 때문에 9시간 느린 11:30분이 되고, 타임스탬프 값은 1024399800이 됩니다. 다시 이 Instant 객체를 벤쿠버 타임존의 ZonedDateTiem 객체로 변환하면 7시간 더 느린 4:30분이 되게 됩니다.

ZonedDateTime zdtSeoul = Year.of(2002).atMonth(6).atDay(18).atTime(20, 30).atZone(ZoneId.of("Asia/Seoul"));
System.out.println("Time in Seoul = " + zdtSeoul);

Instant instant = zdtSeoul.toInstant();
System.out.println("Instant = " + instant + ", Timestamp = " + instant.getEpochSecond());

ZonedDateTime zdtVancouver = instant.atZone(ZoneId.of("America/Vancouver"));
// ZonedDateTime zdtVancouver = ZonedDateTime.ofInstant(instant, ZoneId.of("America/Vancouver")); 와 동일
System.out.println("Tine in Vancouver = " + zdtVancouver);
Time in Seoul = 2002-06-18T20:30+09:00[Asia/Seoul]
Instant = 2002-06-18T11:30:00Z, Timestamp = 1024399800
Tine in Vancouver = 2002-06-18T04:30-07:00[America/Vancouver]

그 밖에 유용한 메소드들

Instant는 타임스탬프를 표현하는 클래스 답게 초나 밀리 초 단위로 시간을 더하거나 빼는 메소드들을 제공합니다. 또한 시간 비교를 위한 메소드도 제공합니다.

Instant worldCup = Instant.ofEpochSecond(1024399800);
System.out.println("2002 World Cup = " + worldCup);
System.out.println("10 seconds later = " + worldCup.plusSeconds(10));
System.out.println("10 seconds earlier = " + worldCup.minusSeconds(10));

Instant now = Instant.now();
System.out.println("Now = " + now);
System.out.println("Is 2002 World Cup before now? " + worldCup.isBefore(now));
System.out.println("Is 2002 World Cup after now? " + worldCup.isAfter(now));
2002 World Cup = 2002-06-18T11:30:00Z
10 seconds later = 2002-06-18T11:30:10Z
10 seconds earlier = 2002-06-18T11:29:50Z
Now = 2017-12-22T08:42:49.252Z
Is 2002 World Cup before now? true
Is 2002 World Cup after now? false