Date는 날짜와 시간을 다룰 목적으로 JDK1.0부터 제공되어온 클래스이다. 그러나 기능이 빈약하여 Calendar이라는 새로운 크래스를 JDK 1.1부터 제공했다. 그러나 이것도 단점이 있어 JDK1.8부터는 java.time패키지를 사용한다.
따라서 책에선 Calendar과 Date도 설명하지만 java.time클래스만 정리하겠다. 또한 필요한 시점에 다시 읽어보도록 한다.
값을 문자열로 나타내거나 문자열을 값으로 변환할때 생각보다 많은 코드가 필요하다. 이걸 편리하게 제공해주는 형식화 클래스가 자바에 존재한다.
DecimalFormat은 숫자를 형식화하여 출력하는데 사용된다. 숫자 데이터를 정수, 부동소수점, 금액등 다양한 형식으로 표현할 수 있게 해준다.
double number = 1234567.89;
DecimalFormat df = new DecimalFormat("#.#E0");
String result = df.format(number);
/* 예시
0 : 1234568
# : 1234568
0.0 : 1234567.9
#.# : 1234567.9
...
*/
Date today = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); // M만 대문자인 이유는 소문자 m이 이미 분(minitue)으로 사용중이라 월(month)는 M이다.
df.format(today);
마찬가지로 날짜를 형식화해서 문자열로 만들거나 문자열을 날짜로 바꿔준다.
JDK1.8부터 추가된 현존 날짜와 시간을 다루는 최신 패키지이다. 패키지 개수는 많지만 핵심적인 클래스는 많지 않다.
| 패키지 | 설명 |
|---|---|
| java.time | 날짜와 시간을 다루는데 필요한 핵심 클래스들을 제공 |
| java.time.chrono | 표준(ISO)이 아닌 달력 시스템을 위한 클래스들을 제공 |
| java.time.format | 날짜와 시간을 파싱하고, 형식화하기 위한 클래스들을 제공 |
| java.time.temporal | 날짜와 시간의 필드(field)와 단위(unit)를 위한 클래스들을 제공 |
| java.time.zone | 시간대와 관련된 클래스들을 제공 |
위 패키지들의 가장 큰 특징은 불변(immutable)하다는 것이다. 이는 스레드 안전을 위한 것이다.
LocalDate는 날짜를 다루며 LocalTime는 시간을 다룬다. LocalDateTime클래스는 날짜와 시간을 모두 함께 다룬다.
여기에 time-zone까지 다뤄야한다면 ZoneDateTime을 사용한다.
LocalDate(날짜) + LocalTime(시간) = LocalDateTime(날짜 & 시간)
LocalDateTime + time-zone = ZoneDateTime
Period는 두 날짜간의 차이를 표현하기 위함. (날짜 - 날짜)
Duration은 시간의 차이를 표현하기 위함. (시간 - 시간)
java.time 패키지에 속한 클래스의 객체를 생성하는 가장 기본적인 방법 두가지이다.
now()은 현재 시간을 인스턴스로 가져오는 메서드이며, of()는 특정 시간을 매개변수로 입력해서 생성한다.
LocalDate date = LocalDate.now(); // 2015-11-23
LocalTime time = LocalTime.now(); // 21:54:01.875
LocalDateTime dateTime = LocalDateTime.now(); // 2015-11-23T21:54:01.875
ZonedDateTime dateTimeInKr = ZonedDateTime.now(); // 2015-11-23T21:54:01.875+09:00[Asia/Seoul]
LocalDate date = LocalDate.of(2015, 11, 23);
LocalTime time = LocalTime.of(23, 59, 59);
LocalDateTime dateTime = LocalDateTime.of(date, time);
ZonedDateTime dateTimeInKr = ZonedDateTime.of(dateTime, ZoneId.of("Asia/Seoul"));
LocalDate, LocalTime, LocalDateTime, ZonedDateTime등 날짜와 시간을 표현하기 위한 클래스들은 모두 Temporal, TemporalAccessor, TemporalAdjuster인터페이스를 구현했다.
Duration과 Period는 TemporalAmount 인터페이스를 구현하였다.
TemporalUnit은 날짜와 시간의 단위를 정의해 놓은 인터페이스.
ChronoUnit은 이 인터페이스를 구현한 열거형.
TemporalFeild는 년, 원, 일 등 날짜와 시간의 필드를 정의해 놓은 것으로 ChronoFild가 해당 인터페이스를 구현했다.
날짜나 시간에서 특정 필드만 값을 얻을때는 get()이나 get으로 시작하는 메서드를 사용한다. 특정 단위의 값을 빼거나 더할때는 plus()또는 minus()를 사용한다.
LocalTime now = LocalTime.now();
int minute = now.getMinute();
LocalDate tomorrow = now.pulsDays(1);
Instant는 에포크 타임(1970-01-01 00:00:00 UTC)부터 경과된 시간을 나노초 단위로 표현한다. 사람에겐 불편하지만 단일 진법이라 계산이 쉽다.
주의할 점은 UTC(+00:00): Coordinated Universal Time 세계 협정시를 기준으로 하므로 한국은 +09:00를 해줘야한다. OffsetDateTime을 사용하면 이런차이를 좀 더 편하게 다룰 수 있다.
참고로 그리니치 천문대 기준시는 GMT(Greenwich Mean Time)이며 UTC와 거의 비슷하지만 UTC가 더 정확하다.
Instant now = Instant.now();
Instant now2 = Instant.ofEpochSecond(now.getEpochSecond());
Instant now3 = Instant.ofEpochSecond(now.getEpochSecond(), now.getNano());
long epochSec = now.getEpochSecond();
int nano = now.getNano();
초 단위와 나노초 단위로 불러오기
static Date from(Instant instant) // Instant -> Date
Instant toInstant() // Date -> Instant
LocalDate + LocalTime -> LocalDateTime
LocalDateTime + 시간대 -> ZonedDateTime
단순히 며칠 후, 몇 년 후(상대적인 계산)를 제외하고 다른 여러가지 검사가 가능하다. 예를 들면 다음해의 첫 날과 같은 검사를 메서드로 제공한다.