본문 바로가기

Java

Java - LocalDateTime (LocalDate, LocalTime), ZonedDateTime, Period, Duration

LocalDate, LocalTime, LocalDateTime, ZonedDateTime 과 같은 API들은 java.util.Date, java.util.Calendar의 단점을 보완하기 위해 Java8에 추가되었다.

 

기존 (java.util.Date, java.util.Calendar) API의 단점

  1. Thread safe 하지 않다.
    동시성 이슈(Concurrency issues)가 존재한다.

  2. 향상된 설계와 이해가 용이하다.
    Date와 Calendar API는 날짜 연산에 적합하지 않게 설계되었다. 새로운 API는 ISO 중심이고, 일관적인 날짜 시간, 기간 도메인 모델을 따르고, 다양한 편의 기능들을 제공한다.

  3. 시간대 (시차) 처리가 불편하다.
    기존 API에서는 시간대역(시차)를 처리하기 위해 로직들을 직접 구현해야 했지만, Local 과 zinedDate/Time API를 활용하면 손쉽게 처리 할 수 있다.

  4. Calendar는 0월 부터 시작한다.
    월(month)은 0부터 일(day of month)은 1부터 시작한다. 엄청 헷갈림.

 

LocalDateTime

LocalDateTime은 LocalDate 객체와 LocalTime 객체를 내부 변수(private final)로 가지고 있다.

이에 따라 LocalDateTime 의 생성함수는 LocalDate 객체와 LocalTime 의 생성 함수를 합쳐놓은 모양이고, 사용되는 함수들도 두 객체의 함수들과 유사하다.

생성방법

// 시스템 시간대역 기준 오늘
LocalDateTime.now();

// 현재 시스템 시간기준 오늘을 특정 지역(Timezone)의 시간으로 변환했을때의 날짜
// TimeZone 이름은 TZDB를 따르며(https://www.iana.org/time-zones) https://nodatime.org/TimeZones 참고
LocalDateTime.now(ZoneId.of("Asia/Seoul"));
LocalDateTime.now(ZoneId.of("America/New_York"));

// of 를 이용한 생성 함수
// of(int year, Month month, int dayOfMonth, int hour, int minute)
// of(int year, Month month, int dayOfMonth, int hour, int minute, int second)
// of(int year, Month month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond)
// of(int year, int month, int dayOfMonth, int hour, int minute)
// of(int year, int month, int dayOfMonth, int hour, int minute, int second)
// of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond)
// of(LocalDate date, LocalTime time)

// 2020년 1월 1일 15시 20분 35초, ISO 기준 날짜 패턴(yyyy-MM-ddT)을 입력 받음
LocalDateTime.parse("2020-01-0T15:20:35")

// 2020년 1월 1일 17시 23분 14초, 사용자 지정 날짜 패턴을 입력 받음)
LocalDateTime.parse("2020.01.01 17-23-14", DateTimeFormatter.ofPattern("yyyy.MM.dd HH-mm-ss"))

 

 

LocalDateTime 에는 날짜를 더하거나 빼는 편리한 기능도 존재 한다.

편리한 기능들

LocalDateTime localDateTime = LocalDateTime.now();
// 2023-09-19T00:18:00.621820200


// minus (시간 빼기)

// minus(TemporalAmount amount)
localDateTime.minus(Duration.ofDays(3)); // localDateTime에서 3일을 뺀다

// minus(long amountToSubtract, TemporalUnit unit)
localDateTime.minus(5, ChronoUnit.DAYS); // localDateTime에서 5일을 뺀다

localDateTime.minusDays(2); // localDateTime에서 2일을 뺀다
localDateTime.minusHours(2); // localDateTime에서 2시간 뺀다
localDateTime.minusXXXXXXX(2);
        

// plus (시간 더하기)
// plus(TemporalAmount amount)
localDateTime.plus(Duration.ofDays(3)); // localDateTime에서 3일을 더한다.

// plus(long amountToSubtract, TemporalUnit unit)
localDateTime.plus(5, ChronoUnit.DAYS); // localDateTime에서 5일을 더한다.

localDateTime.plusDays(2); // localDateTime에서 2일을 더한다.
localDateTime.plusHours(2); // localDateTime에서 2시간을 더한다.
localDateTime.plusXXXXXXX(2);


// with (시간 변경하기)
localDateTime.with(TemporalAdjusters.firstDayOfMonth()); // 날짜를 localDateTime 의 월의 첫번째 날로 변경한다.
localDateTime.with(ChronoField.HOUR_OF_DAY, 10); // 시간을 10시로 변경한다.
localDateTime.withYear(2020); // 년도를 2020년으로 변경한다.

 

ZonedDateTime 

Timezone 이 적용된 날짜와 시간을 다루는 경우, ZonedDateTime을 사용하면 여러가지 편리한 점을 누릴 수 있다.

ZoneId 기반으로 객체를 생성하며, 대부분의 함수들이 LocalDateTime의 그것과 동일하다.

사용가능한 ZoneId 를 조회하는 방법은 아래와 같다.

사용 가능한 ZoneId 조회 하는 법

Set<String> allZoneIds = ZoneId.getAvailableZoneIds();
allZoneIds.forEach(System.out::println);

// 위 코드로 ZoneID를 확인하거나 https://nodatime.org/TimeZones 를 참고한다.

 

Period

Period는 서로 다른 두 날짜의 차이(년, 월, 일 단위)를 나타내는 클래스로, 쉽게 기간을 나타내는 클래스 라고 생각하면 된다.

생성하는 방법은 서로 다른 두 날을 인자로 생성하는 방법과 기간(년, 월, 일수)로 생성하는 방법이 있다.

// 2020년 1월 1일 ~ 2020년 1월 2일 사이 기간 (1일)
Period period = Period.between(LocalDate.of(2020, 1, 1), LocalDate.of(2020, 1, 2));

// 10일
Period period2 = Period.ofDays(10);

// 3달
Period period3 = Period.ofMonths(3);

 

Duration

Period와 유사하며 시간(Time) 단위를 포함하고 있다.

 

 

참고

https://www.baeldung.com/java-8-date-time-intro

https://www.geeksforgeeks.org/new-date-time-api-java8/?ref=lbp 

https://www.geeksforgeeks.org/java-time-localdatetime-class-in-java/?ref=lbp 

https://www.geeksforgeeks.org/java-time-zoneddatetime-class-in-java/?ref=lbp

반응형