날짜 및 시간 API는 Java 8 릴리스의 가장 큰 기능 중 하나입니다. Java는 시작부터 일관된 날짜 및 시간 접근 방식이 부족했으며, Java 8 날짜 및 시간 API는 핵심 Java API에 환영받는 추가입니다.
새로운 Java 날짜 및 시간 API가 필요한 이유는 무엇인가요?
Java 8 날짜 및 시간 API를 살펴보기 전에 이것이 왜 필요한지 알아보겠습니다. Java에서 기존 날짜 및 시간 관련 클래스에는 몇 가지 문제가 있었습니다. 그 중 일부는 다음과 같습니다:
- Java 날짜 및 시간 클래스가 일관되게 정의되지 않았습니다. 우리는 java.util 및 java.sql 패키지에 모두 Date 클래스를 가지고 있습니다. 또한, 포맷팅 및 구문 분석 클래스는 java.text 패키지에 정의되어 있습니다.
- java.util.Date에는 날짜 및 시간 값이 모두 포함되어 있지만, java.sql.Date에는 날짜 값만 포함되어 있습니다. 이것을 java.sql 패키지에 두는 것은 전혀 의미가 없습니다. 또한, 두 클래스 모두 같은 이름을 가지고 있으며, 이는 매우 나쁜 디자인입니다.
- 시간, 타임스탬프, 포맷팅 및 구문 분석에 대해 명확히 정의된 클래스가 없습니다. 파싱 및 포맷팅이 필요한 경우 java.text.DateFormat 추상 클래스를 사용합니다. 일반적으로 SimpleDateFormat 클래스가 파싱 및 포맷팅에 사용됩니다.
- 모든 날짜 클래스는 가변이므로 스레드 안전하지 않습니다. 이것은 Java의 Date 및 Calendar 클래스의 가장 큰 문제 중 하나입니다.
- Date 클래스는 국제화를 제공하지 않으며, 시간대 지원이 없습니다. 그래서 java.util.Calendar 및 java.util.TimeZone 클래스가 소개되었지만, 이들도 위에 나열된 모든 문제를 가지고 있습니다.
Date 및 Calendar 클래스에 정의된 메서드에는 몇 가지 다른 문제가 있지만 위의 문제들로 인해 Java에 견고한 날짜 및 시간 API가 필요하다는 것이 명확해졌습니다. 그래서 Joda Time 이 Java Date Time 요구 사항에 대한 품질 대체품으로 중요한 역할을했습니다.
Java 8 날짜 및 시간 설계 원칙
Java 8 날짜 및 시간 API는 JSR-310 의 구현입니다. 이는 기존의 날짜 및 시간 구현의 모든 결함을 극복하기 위해 설계되었습니다. 새로운 Date Time API의 일부 설계 원칙은 다음과 같습니다:
-
불변성: 새로운 Date-Time API의 모든 클래스는 불변하며 다중 스레드 환경에 적합합니다.
-
관심사 분리: 새 API는 사람이 읽을 수 있는 날짜 및 시간과 기계 시간 (Unix 타임스탬프) 사이에 명확하게 분리됩니다. Date, Time, DateTime, Timestamp, TimeZone 등에 대한 별도의 클래스를 정의합니다.
-
명확성: 메서드는 명확하게 정의되어 있으며 모든 클래스에서 동일한 작업을 수행합니다. 예를 들어, 현재 인스턴스를 가져오려면 now() 메서드를 사용합니다. 이러한 클래스들에는 별도의 클래스 대신 format() 및 parse() 메서드가 정의되어 있습니다.
모든 클래스는 더 나은 처리를 위해 Factory Pattern와 Strategy Pattern을 사용합니다. 한 클래스의 메서드를 사용한 후에는 다른 클래스와 함께 작업하는 것이 어렵지 않습니다.
-
유틸리티 작업: 모든 새로운 날짜-시간 API 클래스에는 플러스, 마이너스, 형식 지정, 구문 분석, 날짜/시간의 별도 부분 가져오기 등과 같은 일반적인 작업을 수행하는 메서드가 함께 제공됩니다.
-
확장 가능: 새로운 날짜 및 시간 API는 ISO-8601 달력 시스템에서 작동하지만 다른 ISO 이외의 달력과도 사용할 수 있습니다.
날짜 및 시간 API 패키지
Java 8 날짜 및 시간 API는 다음 패키지로 구성됩니다.
- java.time: 이것은 새로운 Java 날짜 및 시간 API의 기본 패키지입니다. 모든 중요한 기본 클래스가 이 패키지의 일부이며, LocalDate, LocalTime, LocalDateTime, Instant, Period, Duration 등이 있습니다. 이러한 모든 클래스는 변경할 수 없으며 스레드로부터 안전합니다. 대부분의 경우, 이러한 클래스들은 일반적인 요구 사항을 처리하는 데 충분할 것입니다.
- java.time.chrono: 이 패키지는 ISO 이외의 달력 시스템에 대한 일반적인 API를 정의합니다. 우리는 AbstractChronology 클래스를 확장하여 고유한 달력 시스템을 만들 수 있습니다.
- java.time.format: 이 패키지에는 날짜 및 시간 객체를 형식화하고 구문 분석하는 데 사용되는 클래스가 포함되어 있습니다. 대부분의 경우 java.time 패키지의 주요 클래스가 형식화 및 구문 분석 메서드를 제공하기 때문에 직접 사용하지 않을 것입니다.
- java.time.temporal: 이 패키지에는 시간 객체가 포함되어 있으며 날짜/시간 객체와 관련된 특정 날짜나 시간을 찾을 수 있습니다. 예를 들어, 월의 첫 번째 또는 마지막 날짜를 찾기 위해 사용할 수 있습니다. 이러한 메서드는 항상 “withXXX” 형식을 가지고 있어 쉽게 식별할 수 있습니다.
- java.time.zone Package: 이 패키지에는 다양한 시간대 및 해당 규칙을 지원하기 위한 클래스가 포함되어 있습니다.
Java 8 Date Time API Classes Examples
Java Date Time API의 가장 중요한 부분 중 대부분을 살펴보았습니다. 이제 예제와 함께 Date Time API의 가장 중요한 클래스를 살펴보겠습니다.
1. LocalDate
LocalDate는 yyyy-MM-dd의 기본 형식으로 Date를 나타내는 변경할 수 없는 클래스입니다. 현재 날짜를 가져오기 위해 now() 메서드를 사용할 수 있습니다. 또한 연도, 월 및 날짜에 대한 입력 인수를 제공하여 LocalDate 인스턴스를 만들 수 있습니다.
이 클래스는 특정 시간대에서 날짜를 얻기 위해 ZoneId를 전달할 수 있는 now()에 대한 오버로드된 메서드를 제공합니다. 이 클래스는 java.sql.Date와 동일한 기능을 제공합니다.
LocalDate 메서드에 대한 설명은 주석으로 제공됩니다. 이 프로그램을 실행하면 다음 출력이 표시됩니다.
2. LocalTime
LocalTime은 인간이 읽을 수 있는 형식으로 시간을 나타내는 불변 클래스입니다. 기본 형식은 hh:mm:ss.zzz입니다. LocalDate와 마찬가지로 이 클래스는 시간대 지원을 제공하며 시, 분 및 초를 입력 인수로 전달하여 인스턴스를 생성합니다.
출력:
3. LocalDateTime
LocalDateTime은 yyyy-MM-dd-HH-mm-ss.zzz로 기본 형식을 갖는 불변의 날짜-시간 객체입니다. LocalDate와 LocalTime 입력 인수를 사용하여 LocalDateTime 인스턴스를 생성하는 팩토리 메서드를 제공합니다.
세 가지 예제 모두 날짜/시간을 생성할 때 잘못된 인수를 제공하면 java.time.DateTimeException이 발생하는 것을 볼 수 있습니다. 이것은 RuntimeException이므로 명시적으로 catch할 필요가 없습니다.
우리는 또한 ZoneId를 전달하여 날짜/시간 데이터를 가져올 수 있다는 것을 알아봤는데, 지원되는 ZoneId 값 목록은 해당 JavaDoc에서 확인할 수 있습니다. 위 클래스를 실행하면 다음과 같은 출력이 나옵니다.
4. Instant
Instant 클래스는 기계 판독 가능한 시간 형식으로 작업하는 데 사용됩니다. Instant는 날짜 시간을 유닉스 타임스탬프로 저장합니다.
출력:
Java 8 날짜 API 유틸리티
대부분의 Date Time 주요 클래스는 플러스/마이너스 일, 주, 월 등과 같은 다양한 유틸리티 메서드를 제공합니다. 또한 날짜를 조정하기 위한 TemporalAdjuster를 사용하는 다른 유틸리티 메서드와 두 날짜 간의 기간을 계산하는 메서드도 있습니다.
출력:
자바 8 날짜 구문 분석 및 포맷팅
다양한 형식으로 날짜를 포맷하고 문자열을 구문 분석하여 Date Time 객체를 가져오는 것은 매우 일반적입니다.
출력:
Java Date API Legacy Date Time Support
레거시 날짜/시간 클래스는 거의 모든 애플리케이션에서 사용되므로 하위 호환성을 유지하는 것이 반드시 필요합니다. 그래서 우리는 레거시 클래스를 새 클래스로 변환하거나 그 반대로 변환할 수 있는 여러 유틸리티 메서드가 있습니다.
출력:
레거시 TimeZone
및 GregorianCalendar
클래스의 toString() 메서드가 매우 장황하고 사용자 친화적이지 않음을 알 수 있습니다.
결론
I like this new Date Time API a lot. Some of the most used classes will be LocalDate and LocalDateTime. It’s very easy to work with the new classes. And, having similar methods that does a particular job makes it easy to find. It will take some time from moving legacy classes to new Date Time classes, but I believe it will be worth the time and effort.
Source:
https://www.digitalocean.com/community/tutorials/java-8-date-localdate-localdatetime-instant