그 전까지 사용하면 java.util.Date 클래스는 mutable하기 때문에 thread safe 하지 않다.
클래스 이름이 Date인데 시간까지 다루는 것과 같이, 명명 또한 명확하지 않다.
버그가 발생할 여지가 많다. (타입 안정성이 없고, month도 0부터 시작한다.)
GragorianCalendar(int year, int month, int dayOfMonth) : year에 음수 값이 들어간다면?
enum을 만들어서 Year type, Month type 등을 넣어줘야 타입 안정성이 있다.
날짜 시간 처리가 복잡한 애플리케이션에서는 보통 Joda Time을 쓰고는 했다.
자바8에서 제공하는 Date-Time API
JSR-310 스펙의 구현체를 제공한다.
디자인 철학
Clear
Fluent
Immutable
Extensible
주요 API
기계용 시간 (machine time)과 인류용 시간 (human time)으로 나눌 수 있다.
기계용 시간은 EPOCK (1970년 1월 1일 0시 0분 0초) 부터 현재까지의 타임스탬프를 표현한다.
인류용 시간은 우리가 흔히 사용하는 연,월,일,시,분,초 등을 표현한다.
타임스탬프는 Instant를 사용한다.
특정 날짜(LocalDate), 시간(LocalTime), 일시(LocalDateTime)를 사용할 수 있다.
기간을 표현할 때는 Duration(시간 기반)과 Period(날짜 기반)를 사용할 수 있다.
DateTimeFormatter를 사용해서 일시를 특정한 문자열로 포매팅할 수 있다.
예제
Instant.now() : 현재 UTC(GMT)를 리턴한다.
GMT가 아닌 다른 시간대를 확인하고 싶다면 ZoneId를 사용할 수 있다.
public class Main {
public static void main(String[] args) {
Instant instant = Instant.now();
System.out.println(instant);
}
}
인류용 일시를 표현하는 방법
LocalDateTime.now() : 현재 시스템 Zone에 해당하는 일시를 리턴한다.
LocalDateTime.of() : Local의 특정 일시를 리턴한다.
ZoneDateTime.of() : 특정 Zone의 틀정 일시를 리턴한다.
public class Main {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
LocalDateTime birthday =
LocalDateTime.of(1992, Month.NOVEMBER, 30, 0,0,0);
ZonedDateTime nowInKorea = ZonedDateTime.now(ZoneId.of("Asia/Seoul"));
}
}
기간을 표현하는 방법
Period / Duration (between)
Period _ 인류용
public class Main {
public static void main(String[] args) {
LocalDate today = LocalDate.now();
LocalDate nextYearBirthday = LocalDate.of(2021, Month.NOVEMBER, 30);
Period period = Period.between(today, nextYearBirthday);
Period until = today.until(nextYearBirthday);
long days = ChronoUnit.DAYS.between(today, nextYearBirthday);
System.out.println(days);
}
}
Duration _ 머신용
public class Main {
public static void main(String[] args) {
Instant now = Instant.now();
Instant plus = now.plus(10, ChronoUnit.SECONDS);
Duration between = Duration.between(now, plus);
System.out.println(between.getSeconds());
}
}
public class Main {
public static void main(String[] args) {
LocalDate today = LocalDate.now();
DateTimeFormatter MMddyyyy =
DateTimeFormatter.ofPattern("MM/dd/yyyy");
System.out.println(today.format(MMddyyyy));
LocalDate parse = LocalDate.parse("11/30/1992", MMddyyyy);
System.out.println(parse);
}
}
레거시 API 지원
GregorianCalendar와 Date 타입의 인스턴스를 Instant나 ZonedDateTime으로 변환 가능.
public class Main {
public static void main(String[] args) {
Date date = new Date();
Instant instant = date.toInstant(); //date 타입을 Instant 타입으로 변환
Date newDate = Date.from(instant); // Instant 타입을 date 타입으로도 변환 가능
GregorianCalendar gregorianCalendar = new GregorianCalendar();
LocalDateTime dateTime = gregorianCalendar.toInstant()
.atZone(ZoneId.of("Asia/Seoul"))
.toLocalDateTime();
ZonedDateTime zonedDateTime = gregorianCalendar.toInstant().atZone(ZoneId.of("Asia/Seoul"));
GregorianCalendar.from(zonedDateTime);
ZoneId zoneId = TimeZone.getTimeZone("PsT").toZoneId(); //예전 API to 최근 API
TimeZone timeZone = TimeZone.getTimeZone(zoneId); // 최근 API ro 예전 API
}
}
섹션 5. Date & Time
Date와 Time 소개
java.util.Date
클래스는 mutable하기 때문에 thread safe 하지 않다.GragorianCalendar(int year, int month, int dayOfMonth)
: year에 음수 값이 들어간다면?자바8에서 제공하는 Date-Time API
주요 API
예제
인류용 일시를 표현하는 방법
ZoneDateTime.of() : 특정 Zone의 틀정 일시를 리턴한다.
Period _ 인류용
Duration _ 머신용
파싱 또는 포메팅
LocalDateTime.parse(String, DateTimeFormatter)
레거시 API 지원
GregorianCalendar와 Date 타입의 인스턴스를 Instant나 ZonedDateTime으로 변환 가능.