목표 

  • Java8부터 추가된 LocalDateTime, ZonedDateTime에 대한 기본이해 및 간단한 활용

날짜와 시간을 나타내는 자바 API는 여러가지가 있었지만 기능의 부족함으로 사용이 권장되지는 않았다.

(Calendar, Date 등)

하지만 자바8부터 등장한 java.time API는 이전 API의 결함을 상당부분 해결했고, 앞으로 제 역할을 할 것이라 기대된다. 

 

Instant Class

Instant 클래스는 타임라인의 한 점을 나타낸다.

Immutable, thread-safe 하며 now()로 생성된 인스턴스를 리턴받을 수 있다.

equals(), compareTo() 처럼 비교를 위한 함수를 제공하므로 인스턴스끼리 시간비교가 가능하다.

 
    @Test
    public void Instant_Duration_기본() throws InterruptedException {
        Instant start = Instant.now();
        System.out.println("현재시각(인스턴스) : " + start); // 현재시각(인스턴스) : 2019-10-11T04:50:51.759Z
 
        someComplicatedJob(); // 시간텀을 두기 위해서 임의의 JOB을 수행
 
        // Instant는 한 점을 나타내므로 비교가 가능하다.
        Instant end = Instant.now();
        System.out.println("Instant 사이의 비교 - equals() : " + start.equals(end));
        System.out.println("Instant 사이의 비교 - compareTo() : " + start.compareTo(end));
 
        // 비교를 위해서 Duration 클래스를 사용할 수 있다.
        // Duration : 두 Instant 사이에 있는 시간의 양, 불변 클래스
        Duration timeElapsed = Duration.between(start, end);
        System.out.println("JOB 수행에 걸린시간(밀리초) : " + timeElapsed.toMillis());
        System.out.println("JOB 수행에 걸린시간(초) : " + timeElapsed.getSeconds());
        System.out.println("JOB 수행시간이 마이너스인지 ? " + timeElapsed.isNegative());
    }
    
    
 
cs

 

Duration Class

시간차에 대한 작업을 위해 제공되는 클래스이다.

@Test
public void Duration_활용(){
    Duration duration1 = Duration.ofHours(1); // 1시간 차이
    Duration duration3 = Duration.ofHours(3); // 3시간 차이
 
    // 두 Duration이 2배 이상 차이가 나는지 체크하는 코드
    boolean overDoubleFaster1 = duration1.multipliedBy(2).minus(duration3).isNegative();
    System.out.println("duration3이 duration1 보다 2배 더 빠른가 ? " + overDoubleFaster1);
 
    boolean overDoubleFaster2 = duration1.toNanos() * 2 < duration3.toNanos();
    System.out.println("duration3이 duration1 보다 2배 더 빠른가 ? " + overDoubleFaster2);
}
cs

 

LocalDateTime

실제 사람이 사용하는 시간을 나타내는 API이다. Local(지역)이 접두어로 붙은 것에서 유추할 수 있듯이 여러 지역의 시간대(Time Zone) 정보는 포함하지 않는다.

KST나 UTC처럼 시간대를 지정하는 것이 정확한 표현이지만, 실제 활용에서 이러한 시간대는 잘 사용되지 않고 오히려 방해가 될 수 있으므로 만일 시간대를 필요로 하지 않는 작업이라면 LocalDateTime 사용을 고려한다.

 

LocalDate, LocalTime처럼 날짜, 시간에 특화된 API도 있지만 이 둘을 합쳐서 표현할 수 있는 LocalDateTime이 주로 사용된다.

@Test
public void LocalDate_LocalTime_LocalDateTime_기본(){
    // 구역(Zone) 구분이 없는 지역날짜로 now()나 of()로 생성한다.
    LocalDate nowDate = LocalDate.now();
    LocalDate myBirthDay = LocalDate.of(1988, Month.MAY, 26); // '월'을 enum으로 줄 수도 있다.
 
    System.out.println("현재날짜 : " + nowDate); // 2019-10-11
    System.out.println("현재날짜 + 7일 : " + nowDate.plusDays(7L)); // 2019-10-18
    System.out.println("현재날짜 + 7일 : " + nowDate.plusWeeks(1L)); // 2019-10-18
    System.out.println("현재날짜 - 7일 : " + nowDate.minus(Period.ofDays(7))); // 2019-10-04
 
    LocalTime nowtime = LocalTime.now();
    System.out.println("현재시각 : " + nowtime); // 15:16:22.909
    System.out.println("현재시각 + 1시간 : " + nowtime.plusHours(1L)); // 16:16:22.909
    System.out.println("현재시각에서 시간만 3으로 변경 : " + nowtime.withHour(3)); // 03:16:22.909
 
 
    LocalDateTime nowDateTime = LocalDateTime.now();
    System.out.println("현재시각 : " + nowDateTime); // 2019-10-11T15:16:22.909
    System.out.println("현재시각 + 1시간 : " + nowDateTime.plusHours(1L)); // 2019-10-11T16:16:22.909
    System.out.println("현재시각에서 시간만 3 : " + nowDateTime.withHour(3)); // 2019-10-11T03:16:22.909
}
cs

 

ZonedDateTime

LocalDateTime에서 시간대(Time Zone) 개념이 추가된 클래스로 기본적인 사용방법은 비슷하다.

다음과 같이 사용가능한 TimeZoneId를 출력해보면 많은 수가 있는것을 알 수 있다.

@Test
public void ZoneId(){
    // 각 시간대는 America/New_York, Europe/Berlin 등 ID가 존재한다.
    Set<String> availableZoneIds = ZoneId.getAvailableZoneIds(); // 이용할 수 있는 모든 시간대를 얻는다.
    for(String str : availableZoneIds){
        System.out.println(str); // Asia/Aden, America/Chicago, Europe/Luxembourg ...
    }
}
cs

많은 ZoneId 중에서도 아마 많이 사용할 시간대는 Asia/Seoul 과 UTC 일 것이다.

해당 타임존을 인자로하여 ZonedDateTime을 생성 후 출력해보면 인자로 준 시간대 정보가 같이 출력된다. 

UTC의 경우 표준이니 별다른 내용이 없지만, Asia/Seoul의 경우는 표준 UTC 06시23분에 9시간이 더해져서 15시23분임을 알 수 있다.

LocalDateTime에 타임존을 추가하거나 ZonedDateTime에 타임존을 제거하면서 상호변환이 가능하다.

@Test
public void ZonedDateTime(){
    ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Asia/Seoul"));
    System.out.println(now); // 2019-10-11T15:23:08.605+09:00[Asia/Seoul]
 
    ZonedDateTime now2 = ZonedDateTime.now(ZoneId.of("UTC"));
    System.out.println(now2); // 2019-10-11T06:23:08.605Z[UTC]
 
}
cs
@Test
public void ZonedDateTime_to_LocalDateTime(){
    ZonedDateTime nowUTC = ZonedDateTime.now(ZoneId.of("UTC"));
    System.out.println(nowUTC);
 
    LocalDateTime nowSeoul = nowUTC.withZoneSameInstant(ZoneId.of("Asia/Seoul")).toLocalDateTime();
    System.out.println(nowSeoul);
 
    ZonedDateTime nowSeoulZonedTime = nowSeoul.atZone(ZoneId.of("Asia/Seoul"));
    System.out.println(nowSeoulZonedTime);
}
cs

ZonedDateTime 인스턴스를 문자열(String)로 변경하거나 반대의 경우도 가능하다. 

변환시 DateTimeFormatter를 인자로하여 원하는 패턴으로 변환한다.

@Test
public void formatting(){
    ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Asia/Seoul"));
 
    String nowStr1 = now.format(DateTimeFormatter.ISO_DATE_TIME); // 2019-10-11T15:48:07.039+09:00[Asia/Seoul]
    String nowStr2 = now.format(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss z")); // 2019/10/11 15:48:07 KST
    String nowStr3 = now.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL)); // 2019년 10월 11일 금요일 오후 3시 48분 07초 KST
    String nowStr4 = now.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withLocale(Locale.US)); // Friday, October 11, 2019 3:48:07 PM KST
 
    ZonedDateTime now1 = ZonedDateTime.parse(nowStr1);
    ZonedDateTime now2 = ZonedDateTime.parse(nowStr2, DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss z"));
    ZonedDateTime now3 = ZonedDateTime.parse(nowStr3, DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL));
    ZonedDateTime now4 = ZonedDateTime.parse(nowStr4, DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withLocale(Locale.US));
 
    System.out.println(now1);
    System.out.println(now2);
    System.out.println(now3);
    System.out.println(now4);
}
cs

 

EpochTime -> LocalDateTime 변환

시간을 표현하는 Long값인 EpochTime을 LocalDateTime으로 변환할 수 있다.

@Test
public void Epoch_to_LocalDateTime(){
    // Epoch Time을 LocalDateTime으로 변경한다.
    LocalDateTime now3 = LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis()), ZoneId.of("Asia/Seoul"));
    System.out.println(now3);
 
    LocalDateTime now4 = LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis()), ZoneId.of("UTC"));
    System.out.println(now4);
}
cs

 


읽어주셔서 감사합니다. 도움이 되셨다면 광고 클릭 부탁드립니다.

모두 힘내세요! : )

 

 

 

'개발 > JAVA' 카테고리의 다른 글

ExecutorService 사용법  (0) 2020.12.01
Comparator, Comparable 어떻게 사용할까?  (0) 2020.11.29
Collections를 이용한 정렬(sort method) 활용  (0) 2017.05.09
BigDecimal & BigInteger  (0) 2017.04.18
Array 와 ArrayList 사이의 변환  (0) 2017.03.28

+ Recent posts