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. LocalDate
와 LocalTime
1) LocalDate
클래스와 LocalTime
클래스
LocalDate
클래스는 날짜를 표현하는 데 사용되며,LocalTime
클래스는 시간을 표현하는 데 사용된다.java.time
패키지에 포함된 대부분의 클래스들은 이 두 클래스를 확장한 것이 많으므로, 우선 이 두 클래스를 잘 이해하는 것이 중요하다.
2) 날짜와 시간 객체의 생성
LocalDate
와LocalTime
클래스는 객체를 생성하기 위해서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) 날짜와 시간 객체에 접근하기
LocalDate
와LocalTime
클래스는 특정 필드의 값을 가져오기 위해서 다음과 같이 다양한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) 날짜와 시간 객체의 필드값 변경
LocalDate
와LocalTime
클래스는 날짜와 시간 객체에 접근하여 특정 필드의 값을 변경하기 위해서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) 날짜와 시간 객체의 비교
LocalDate
와LocalTime
클래스에도 객체를 비교할 수 있는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