Skip to content

21. java.time 패키지


1. 키워드

  • java.time 패키지
  • LocalDate 클래스와 LocalTime 클래스


2. java.time 패키지

1) 자바에서의 날짜 및 시간 처리

  • JDK 1.0에서는 Date 클래스를 사용하여 날짜에 관한 처리를 수행했다.
  • 하지만 Date 클래스는 현재 대부분의 메서드가 사용을 권장하지 않고 있다.
  • JDK 1.1부터 새롭게 제공된 Calendar 클래스는 날짜와 시간에 대한 정보를 손쉽게 얻을 수 있었다.
  • 하지만 Calendar 클래스는 다음과 같은 문제점을 가지고 있다.


1] Calendar 인스턴스는 불변 객체(Immutable Object)가 아니라서 값이 수정될 수 있다.

2] 윤초(Leap Second)와 같은 특별한 상황을 고려하지 않는다.

3] Calendar 클래스에서는 월(Month)을 나타낼 때 1월부터 12월을 0부터 11까지로 표현해야 하는 불편함이 있다.


  • 따라서 많은 자바 개발자들은 Calendar 클래스뿐만 아니라 더 나은 성능의 Joda-Time이라는 라이브러리를 함께 사용해 왔다.
  • java.time 패키지는 위와 같은 문제점을 모두 해결했으며, 다양한 기능을 지원하는 다수의 하위 패키지를 포함하고 있다.


2) java.time 패키지

  • Java SE 8부터 제공되는 java.time 패키지에는 자바에서 날짜와 시간을 다루는 데 사용되는 필수 클래스들이 포함되어 있다.
  • 또한, 다음과 같은 다양한 기능을 하는 하위 패키지를 포함하고 있다.


1] java.time.chrono

  • ISO-8601에 정의된 표준 달력 이외의 달력 시스템을 사용할 때 필요한 클래스들

2] java.time.format

  • 날짜와 시간에 대한 데이터를 구문분석하고 형식화하는 데 사용되는 클래스들

3] java.time.temporal

  • 날짜와 시간에 대한 데이터를 연산하는 데 사용되는 보조 클래스들

4] java.time.zone

  • 타임 존(Time-Zone)과 관련된 클래스들


  • java.time 패키지는 기존에 사용되던 Calendar 클래스의 단점을 보완하였다.
  • 따라서 해당 패키지에 속하는 모든 클래스의 인스턴스는 불변 객체로 생성된다.
  • 즉, java.time 패키지에 포함되는 클래스의 메서드들은 모두 새로운 객체를 생성하여 반환하고 있다.


3) java.time 패키지의 구성 클래스

  • 기존의 Calendar 클래스는 날짜와 시간을 한 번에 표현했지만, java.time 패키지에서는 별도로 구분하여 처리한다.
  • LocalDate 클래스는 날짜를 표현할 때 사용하며, LocalTime 클래스는 시간을 표현할 때 사용한다.
  • 또한, 기존의 Calendar 클래스처럼 날짜와 시간을 한 번에 표현하고 싶을 때는 LocalDateTime 클래스를 사용한다.
  • ZonedDateTime 클래스는 특정 타임 존에 해당하는 날짜와 시간을 다루는 데 사용한다.
  • 또한, 기존의 Date 클래스와 비슷한 용도로 사용되는 Instant 클래스가 있다.
  • Instant 클래스는 특정 시점의 날짜와 시간을 나노초(nanosecond) 단위로 표현하는 타임 스탬프(Time-Stamp)를 다루는 데 사용된다.
  • Period 클래스는 두 날짜 사이의 차이를 표현하는 데 사용되며, Duration 클래스는 두 시각 사이의 차이를 표현하는 데 사용된다.


3. LocalDateLocalTime

1) LocalDate 클래스와 LocalTime 클래스

  • LocalDate 클래스는 날짜를 표현하는 데 사용되며, LocalTime 클래스는 시간을 표현하는 데 사용된다.
  • java.time 패키지에 포함된 대부분의 클래스들은 이 두 클래스를 확장한 것이 많으므로, 우선 이 두 클래스를 잘 이해하는 것이 중요하다.


2) 날짜와 시간 객체의 생성

  • LocalDateLocalTime 클래스는 객체를 생성하기 위해서 now()of() 메서드라는 클래스 메서드를 제공한다.
  • now() 메서드는 현재의 날짜와 시간을 이용하여 새로운 객체를 생성하여 반환한다.
  • 하지만 of() 메서드는 전달된 인수를 가지고 특정 날짜와 시간을 표현하는 새로운 객체를 생성하여 반환한다.


LocalDate today = LocalDate.now();
LocalTime present = LocalTime.now();

System.out.println(today + " " + present);

// static LocalDate of(int year, int month, int dayOfMonth)
LocalDate birthDay = LocalDate.of(1982, 02, 19);

// static LocalTime of(int hour, int minute, int second, int nanoOfSecond)
LocalTime birthTime = LocalTime.of(02, 02, 00, 100000000);

System.out.println(birthDay + " " + birthTime);

// 2021-06-20 21:23:36.856274
// 1982-02-19 02:02:00.100


  • of() 메서드는 위의 예제에서 사용된 메서드 시그니처 이외에도 다양한 형태가 오버로딩되어 제공된다.


3) 날짜와 시간 객체에 접근하기

  • LocalDateLocalTime 클래스는 특정 필드의 값을 가져오기 위해서 다음과 같이 다양한 getter 메서드를 제공한다.


  • 기존의 Calendar 클래스에서는 1월을 0으로 표현하여 월의 범위가 0 ~ 11이었으며, 요일은 일요일부터 1로 표현했다.
  • 하지만 java.time 패키지에서는 1월을 1로 표현하여 월의 범위가 1 ~ 12가 되었으며, 요일은 월요일부터 1로 표현하도록 변경되었다.


Note

  • Calendar 클래스와 java.time 패키지의 클래스를 같이 사용할 때에는 특히 위와 같은 차이점에 주의해야 한다.


LocalDate today = LocalDate.now();

System.out.println("올해는 " + today.getYear() + "년입니다.");

System.out.println("이번달은 " + today.getMonthValue() + "월입니다.");

System.out.println("오늘은 " + today.getDayOfWeek() + "입니다.");

System.out.println(
  "오늘은 1년 중 " + today.get(ChronoField.DAY_OF_YEAR) + "일째 날입니다."
);

// 올해는 2021년입니다.
// 이번달은 6월입니다.
// 오늘은 SUNDAY입니다.
// 오늘은 1년 중 171일째 날입니다.
LocalTime present = LocalTime.now();

System.out.println(
  "현재 시각은 " +
  present.getHour() +
  "시 " +
  present.getMinute() +
  "분입니다."
);

// 현재 시각은 21시 31분입니다.


4) TemporalField 인터페이스

  • TemporalField 인터페이스는 월(Month-of-Year)과 시(Hour-of-Day)와 같이 날짜와 시간과 관련된 필드를 정의해 놓은 인터페이스이다.
  • 이 인터페이스를 구현하여 날짜와 시간을 나타낼 때 사용하는 열거체가 바로 ChronoField이다.
  • java.time 패키지를 구성하는 클래스의 메서드에서는 이 열거체를 이용하여 날짜와 시간을 처리하고 있다.


LocalTime present = LocalTime.now();

String ampm;

if (present.get(ChronoField.AMPM_OF_DAY) == 0) {
  ampm = "오전";
} else {
  ampm = "오후";
}

System.out.println(
  "지금은 " +
  ampm +
  " " +
  present.get(ChronoField.HOUR_OF_AMPM) +
  "시입니다."
);

// 지금은 오후 9시입니다.


5) 날짜와 시간 객체의 필드값 변경

  • LocalDateLocalTime 클래스는 날짜와 시간 객체에 접근하여 특정 필드의 값을 변경하기 위해서 with() 메서드를 사용한다.
  • with() 메서드를 사용하면 값이 변경될 필드를 사용자가 직접 명시할 수 있다.
  • 또한, 특정 필드의 값을 변경하기 위해 미리 정의되어 제공되는 다양한 with() 메서드를 사용할 수도 있다.


LocalDate today = LocalDate.now();
System.out.println("올해는 " + today.getYear() + "년입니다.");

LocalDate otherDay = today.withYear(1982);
System.out.println("올해는 " + otherDay.getYear() + "년입니다.");

// 올해는 2021년입니다.
// 올해는 1982년입니다.
LocalTime present = LocalTime.now();
System.out.println("현재 시각은 " + present.getHour() + "시입니다.");

LocalTime otherTime = present.withHour(8);
System.out.println("현재 시각은 " + otherTime.getHour() + "시입니다.");

// 현재 시각은 21시입니다.
// 현재 시각은 8시입니다.


  • with() 메서드 이외에도 특정 필드의 값을 더하거나 뺄 수 있는 다양한 plus()minus() 메서드도 제공된다.


LocalTime present = LocalTime.now();
System.out.println(
  "현재 시각은 " + present.get(ChronoField.HOUR_OF_DAY) + "시입니다."
);

LocalTime otherTime = present.plus(2, ChronoUnit.HOURS);
System.out.println("바뀐 시간은 " + otherTime.getHour() + "시입니다.");

LocalTime anotherTime = present.minus(6, ChronoUnit.HOURS);
System.out.println("바뀐 시간은 " + anotherTime.getHour() + "시입니다.");

// 현재 시각은 21시입니다.
// 바뀐 시간은 23시입니다.
// 바뀐 시간은 15시입니다.


6) 날짜와 시간 객체의 비교

  • LocalDateLocalTime 클래스에도 객체를 비교할 수 있는 compareTo() 메서드가 오버라이딩되어 있다.
  • 하지만 더욱 편리하게 날짜와 시간 객체를 서로 비교할 수 있도록 다음과 같은 메서드를 제공한다.


1] isEqual() 메서드

  • equals() 메서드와는 달리 오직 날짜만을 비교 (LocalDate 클래스에서만 제공)

2] isBefore() 메서드

  • 두 개의 날짜와 시간 객체를 비교하여 현재 객체가 명시된 객체보다 앞선 시간인지를 비교

3] isAfter() 메서드

  • 두 개의 날짜와 시간 객체를 비교하여 현재 객체가 명시된 객체보다 늦은 시간인지를 비교


LocalDate today = LocalDate.now();
LocalDate otherDay = LocalDate.of(1982, 02, 19);

System.out.println(today.compareTo(otherDay));
System.out.println(today.isBefore(otherDay));
System.out.println(today.isEqual(otherDay));

// 39
// false
// false

References