날짜와 시간
1. 날짜의 경우 윤년 ,각 달의 일수 등을 고려해야함
2. 일광 절약 시간 변환(DST)
예시 특정 지역에서는 3월의 마지막 일요일에 DST가 시작되어 10월의 마지막 일요일에 종료된다. 이 기간 동안 발생하는 모든 날짜와 시간 계산은 1시간을 추가하거나 빼는 로직을 포함해야 함.
3. 타임존 계산
세계가 다양한 타임존으로 나뉘어 있다. 타임존 간의 날짜와 시간변환을 정확히 계산하는 것은 복잡하다.
서울의 타임존 Asia/Seoult, UTC +9 . 베를린 타임존 UTC + 1
둘 차이는 8시간이다. 근데 만약 베를린에서 DST가 적용되면 타임존 차이는 7시간으로 줄어듬.
자바 날짜와 시간 라이브러리 역사
JDK 1.0 (java.utilDate)
- 문제점
- 타임존 처리 부족 : 초기 Date 클래스는 타임존(time zone)을 제대로 처리하지 못했다.
- 불편한 날짜 시간 연산 : 날짜 간 연산이나 시간의 증감 등을 처리하기 어려웠다.
- 불변 객체 부재: Date 객체는 변경 가능(mutable)하여, 데이터가 쉽게 변경될 수 있었고 이로 인해 버그가 발생하기 쉬웠음.
- 해결책
- JDK 1.1에서 java.util.Calendar 클래스 도입으로 타임존 지원 개선
- 날짜 시간 연산을 위한 추가 메소드 제공
JDK 1.1(java.util.Calendar)
- 문제점
- 사용성 저하 : Calendar는 사용하기 복잡하고 직관적이지 않았다.
- 성능 문제: 일부 사용 사례에서 성능이 저하되는 문제가 있었다.
- 불변 객체 부재: Calendar 객체도 변경 가능하여, 사이드 이펙트, 스레드 안정성 문제가 있었음
- 해결책
- Joda-Time 오픈소스 라이브러리의 도입으로 사용성, 성능,불편성 문제 해결
JDK 8 (java.time 패키지)
- java.time 패키지는 이전 API의 문제점을 해결하면서, 사용성,성능,스레드 안정성, 타임존 처리 등에서 크게 개선됨.
변경 불가능한 불변 객체 설계로 사이드 이펙트. , 스레드 안정성 보장, 직관적인 API 제공.
LocalDate,LocalTime,LocalDateTiem -> 세계 시간대 고려하지 않는 경우 사용. 특정 지역의 날짜와 시간만 고려할때
ZonedDateTime : 시간대를 고려한 날짜와 시간을 표현할 때 사용, 시간대를 표현하는 타임존 포함, 일광 절약 시간제 적용
OffsetDateTime : 타임존은 없고, UTC로 부터의 시간대 차이인 고정된 오프셋만 포함.
시간의 간격(기간)을 표현하는 방법 두 가지
- Period : 두 날짜 사이의 간격을 년, 월, 일 단위로 나타낸다.
- Duration: 두 시간 사이의 간격을 시, 분, 초 단위로 나타낸다.
LocalDateTime -> 그냥 equals() 가 아닌 isEquals()를 통해 비교해야함 -> 다른 날짜시간과 시간적으로 동일한지 비교. 시간이 같으면 true를 반환
ZoneDateTime은 구체적인 지역 시간대를 다룰 때 사용, 일광 절약 시간을 자동으로 처리할 수 있다. 사용자 지정 시간대에 따른 시간 계산이 필요할 때 적합하다.
OffsetDateTime은 UTC와의 시간 차이만을 나타낼 때 사용하며, 지역 시간대의 복잡성을 고려하지 않는다. 시간대 변환 없이 로그를 기록하고 , 데이터를 저장하고 처리할 때 적합.
기계 중심의 시간 - Instant
1970년 1월 1일 00:00:00 UTC부터 현재까지 경과된 시간을 초 단위로 표현한 것.
Instant 특징
장점 :
시간대 독립성 : Instant는 UTC를 기준으로 하므로, 시간대에 영향을 받지 않는다. 이는 전 세계 어디서나 동일한 시점을 가리키는데 유용하다.
고정된 기준점 : 1970년 1월 1이 ㄹUTC를 기준으로 하기에 시간 계산 및 비교가 명확하고 일관됨
단점 :
시간대 정보 부재 : Instant에는 시간대 정보가 포함되어 있지 않아 특정 지역의 날짜와 시간으로 변환하려면 추가적인 작업이 필요하다.
- Instant 정리
- 조금 특별한 시간, 기계 중심, UTC 기준
- 에포크 시간으로부터 흐른 시간을 초 단위로 저장
- 전세계 모든 서버 시간을 똑같이 맞출 수 있음. 항상 UTC 기준이므로 한국에 있는 Instant, 미국에 있는 Instant가 똑같다.
- 서버 로그, epoch 시간 기반 계산이 필요할 때, 간단히 두 시간의 차이를 구할 때
- 단점 : 초 단위의 간단한 연산 가능, 복잡한 연산 못함
- 대안 : 날짜 계산 필요하면 LocalDateTime 또는 ZonedDateTime 사용
Period
두 날짜 사이의 간격을 년,월,일 단위로 나타낸다.
public class Period {
private final int years;
private final int months;
private final int days;
}
Duration
두 시간 사이의 간격을 시, 분 , 초 (나노초) 단위로 나타냄
public class Duration {
private final long seconds;
private final int nanos;
}
내부에서 초를 기반으로 시, 분 , 초를 계산해서 사용한다.
1분 = 60초
1시간 = 3600