java 날짜 계산 (java.time)
java에서는 날짜를 추출/계산 할 수있는 여러가지 방법이 있지만, 익히 알고 있는 방법은
Calendar 클래스를 이용하는 것이다.
Calendar 은 JDK 1.1 부터 제공되었고 유용하게 사용되었으나, 몇가지 문제점이 있다.
- Calendar 인스턴스는 불변 객체가 아니어서 수정이 가능하다.
- 윤초와 같은 특별한 상황은 고려되지 않았다.
- Calendar 은 1월 ~ 12월 을 0 ~ 11 로 표현해야 한다.
JDK 8 이후 버전부터는 새로운 날짜와 시간 API 인 java.time 패키지를 제공한다.
아래는 java.time 이하 에서 제공되는 하위 패키지 들이다.
아래 내용은 gbsb.tistory.com/302에서 발췌하였다.
- chrono : ISO-8601 에 정의된 표준달력 외 달력시스템 사용 시 이용되는 클래스 패키지
- format : 날짜와 시간에 대한 데이터를 분석하고 형식화 하는 클래스 집합 패키지.
- temporal : 날짜와 시간에 대한 연산에 사용되는 보조 클래스들 집합 패키지
- zone : Time-Zone 에 관련 클래스 집합 패키지
패키지 외 여러 클래스들이 존재하지만 자주 사용되는 몇가지에 대해 정의한다.
- LocalDate : 날짜를 표현 시 사용. ( 타임존에 따른 시간 변환 불가 )
- LocalTime : 시간을 표현 시 사용 ( 타임존에 따른 시간 변환 불가 )
- LocalDateTime : 날짜와 시간을 한 번에 표현 시 사용. ( 타임존에 따른 시간 변환 불가 )
- ZonedDateTime : 특정 Time-zone 에 해당하는 날짜와 시간을 다룰 때 사용.
- Instant : 특정 시점의 날짜와 nanosecond 단위로 표현하는 time-stamp 다룰 때 사용.
- Period : 두 날짜 사이의 차이를 표현 시 사용
- Duration : 두 시각 차이를 표현 시 사용
- TemporalField : 월(month-of-year) 과 시(hour-of-day) 와 같이 날짜, 시간과 관련된 필드를 정의한 인터페이스.
이 인터페이스를 구현하여 날짜와 시간을 나타낼 때 사용하는 열거체가 ChronoField 이다
앞서 얘기한데로 Canendar 클래스는 1월 - 0 , 12월 - 11 로 표현하였으나,
java.time 부터는 1월 - 1, 12월 - 12로 표현한다. 또한 요일은 월요일 - 1, 일요일 - 7 로
표기한다.
[ LocalDate 생성 & 사용 ]
위 클래스들은 public 생성자를 제공하지 않기 때문에 객체를 생성할 때 now(), of(), parse() 과 같은
정적 메소드를 사용해야 한다.
LocalDate currDate = LocalDate.now(); System.out.println( "Today : " + currDate ); >>> 2020-11-06 |
now() : 현재 날짜 또는 시간을 이용하여 새로운 객체를 생성 및 리턴
of() : 지정한 날짜와 시간을 표현하는 객체를 생성 및 리턴
parse() : 지정한 날짜와 시간을 표현하는 객체를 생성 및 리턴
[ LocalTime 생성 & 사용 ]
- LocalDate 와 매우 유사하며, 기본 포멧은 HH:mm:ss.SSS 이다.
LocalTime currTime = LocalTime.now(); System.out.println( "currTime : " + currTime ); >>> 02:30:27.123 LocalTime seoulTime = LocalTime.now( ZoneId.of("Asiz/Seoul") ) ); System.out.println( "seoulTime : " + seoulTime ); >>> 02:30:27.124 System.out.println( "targetTime : " + targetTime ); >>> 02:30:10 LocalTime targetPlusTime = targetTime.plusHour(8); System.out.println("targetPlusTime : " + targetPlusTime ); >>> 10:30:10 LocalTime targetMinusTime = targetTime.minusHour(1); System.out.println( "targetMinumTime : " + targetMinumTime ); |
위 샘플들은 LocalDate, LocalTime 으로 분리하였으나 실제 사용되는 함두는 두 클래스(LocalDate, LocalTime)
다 유사하다.
즉, LocalDate 클래스에도 plusDays(..), plus(..), plusHours(..) 등 plusXxxx(...) 와 minusXxxx(...) 함수들이 제공된다.
[ LocalDateTime 객체 생성 & 사용 ]
- LocalDateTime 클래스는 LocalDate 와 LocalTime 2개의 기능을 모두 제공하는 클래스라고 생각하면 된다.
또한 제공되는 함수도 유사하다. ( 기본 포멧은 yyyy-MM-ddTHH:mm:ss.SSS 이다. )
LocalDateTime currLDT = LocalDateTime.now(); System.out.println( "currLDT : " + currLDT ); >>> 2020-11-05T02:30:10.235 LocalDateTime targetLDT = LocalDateTime.parse("2020-11-05T02:30:10.123"); System.out.println( "targetLDT : " + targetLDT ); >>> 2020-11-05T02:30:10.123 System.out.println( "targetLDT2 : " + targetLDT2 ); >>> 1981-02-09T06:10:11 |
with() : 생성된 객체( Local.... ) 의 특정 필드값을 변경하기 위해서 사용.
- with(TemporalField field, long newValue) : LocalDate 객체에서 특정 필드(TemporalField) 를 새로운 값(long)
으로 설정한 객체를 반환한다.
- withYear(int year) : LocalData 객체에서 연도 필드를 새로운 값(int) 로 설정 및 반환
- withMonth(int month) : LocalDate 객체에서 월(MONTH_OF_YEAR) 필드를 새로운 값(int) 으로 설정 및 반환
- withDayOfMonth(int dayOfMonth) : LocalData 객체에서 일(DAY_OF_MONTH) 필드를 새로운 값(int) 으로 설정 및 반환.
- withDayOfYear(int dayOfYear) : LocalDate 객체에서 DAY_OF_YEAR 필드를 새로운 값(int) 으로 설정 및 반환
LocalTime 에서는 with(...) withHour(...), withMinute(...), withSecond(...), withNano(...) 등이 존재한다.
with..(...) 함수 외에 plus(), minus() 함수도 제공하고 있다.
[ 날짜 & 시간 객체의 비교 ]
- isEqual() : 오직 날짜가 같은지 비교하며, LocalDate 클래스에서만 제공. ( boolean )
- isBefore() : 객체를 비교하여 이전인지 여부 확인 ( boolean )
- isAfter() : 객체를 비교하여 이후 인지 여부 확인 ( boolean )
[ java.time.Instant ]
Instant.now() 를 호출 시 현재 시간 Instant 를 획득할 수 있다. (UTC 기준 ISO 포멧이다.)
또한 초단위 또는 밀리초 단위의 Timestamp 값을 long 타입으로 얻을 수 있다.
Instant currInstant = Instant.now(); System.out.println( "UTC+0 기준 현재 시간 : " + currInstant ); ( 현재 한국 시간은 2020-11-10 08:21 이다. ) |
Instant 클래스와 ZoneDateTime 클래스는 특정 메서드를 통해 객체가 서로 변환이 가능하다.
바로 atZone(..) 메소드와 toInstant() 메소드 이다.
Instant currInstant = Instant.now(); |
[ java.time.ZoneDateTime ]
ZoneDateTime 클래스는 타임존 또는 시차가 적용되는 필요한 날짜와 시간정보를 나타낼 때 사용하면 용이하다.
public 생성자는 제공하지 않으며, 정적 메소드를 통하여 객체를 생성한다.
또한 format() 메소드에 DateTimeFormatter 객체를 사용하여 원하는 문자열로 포멧 변환이 가능하다.
DateTimeFormatter 은 ofPattern(...) 을 이용하여 원하는 포멧을 정의하거나 DateTimeFormatter 에서 제공하는
정적 필드( Ex: DateTimeFormatter.ISO_DATE_TIME.. ) 를 이용할 수 있다.
날짜 시간에 대한 언어 표현은 withLocale( Locale.~ ) 함수를 사용하여 다양하게 구현할 수 있다.
System.out.println( "한국 현재 시간 ZoneDateTime: " + ZoneDateTime.now() ); |
[ ZoneId & ZoneOffset ]
ZoneId 는 타임존으로 지정한 지역의 시간코드, ZoneOffset 은 UTC 기준 시간차 (양수/음수) 를 나타낸다.
예로 한국 서울의 ZoneId : Asia/Seoul & ZoneOffSet : +0900 이다.
System.out.println( "ZoneOffset.of('+09:00') : " + ZoneDateTime.now(ZoneOffset.of("+09:00")) ); |