본문 바로가기
자바

[모던 자바 인 액션] 날짜와 시간 API

by __Minnie_ 2025. 5. 8.
기존 날짜와 시간 API의 문제점

1. Date라는 하나의 클래스로 날짜와 시간을 모두 관리

2. 1900년을 기준으로 하는 오프셋, 0에서 시작하는 달 인덱스 등 모호한 설계 -> 2017년 9월 21일을 표현하려면 아래처럼 작성 필요

Date date = new Date(117, 8, 21);

 

3. toString으로 반환되는 문자열 활용도가 떨어짐

4. Calender라는 클래스를 대안으로 제공했지만, 달 인덱스는 여진히 0에서 시작하였음

5. DateFormat은 스레드에 안전하지 않았음

 

 

LocalDate, LocalTime, LocalDateTime, Instant

 

1. LocalDate

시간을 제외한 날짜를 표현하는 불변 객체

# LocalDate 객체 생성
LocalDate date = LocalDate.of(2014, 3, 18);

# 연도 추출
int year = date.getYear();

# 월 추출
Month month = date.getMonth();

# 일 추출
int day = date.getDayOfMonth();

# 요일 추출
DayOfWeek dow = date.getDayOfWeek();

# 일 수
int len = date.lengthOfMonth();

# 윤년 여부
boolean leap = date.isLeapYear();

# 연도 추출 (TemporalField를 정의한 ChronoField 사용)
int y = date.get(ChronoField.YEAR);

# 월 추출
int m = date.get(ChronoField.MONTH_OF_YEAR);

# 일 추출
int d = date.get(ChronoField.DAY_OF_MONTH);

# 문자열에서 객체 생성
LocalDate date = LocalDate.parse("2017-09-21");

 

 

2. LocalTime

시간을 표현하는 불변 객체

# LocalTime 객체 생성
LocalTime time = LocalTime.of(13, 45, 20);

# 시간 추출
int hour = time.getHour();

# 분 추출
int minute = time.getMinute();

# 초 추출
int second = time.getSecond();

# 문자열에서 객체 생성
LocalTime time = LocalTime.parse("13:45:20");

 

3. LocalDateTime

LocalDate와 LocalTime을 쌍으로 갖는 복합 클래스

# LocalDateTime 객체 생성
LocalDateTime dt1 = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45, 20);

# LocalDate, LocalTime 인스턴스로 생성
LocalDateTime.of(date, time);

LocalDateTime dt3 = date.atTime(13, 45, 20);

date.atTime(time);

time.atDate(date);

# LocalDateTime에서 LocalDate추출
LocalDate date1 = dt1.toLocalDate();

# LocalDateTime에서 LocalTime추출
LocalTime time1 = dt1.toLocalTime();

 

4. Instant

유닉스 시간을 기준으로 특정 지점까지의 시간을 초로 표현. LocalDateTime이 사람이 사용하는 시간이라면 Instant는 기계가 사용하는 시간

Instant instant = Instant.ofEpochSecond(1387584000L);

Instant now = Instant.now();

 

Duration과 Period

 

1. Duration

시간과 시간 사이의 지속시간을 관리. 날짜와 날짜 사이의 지속시간은 관리 X

Duration d1 = Duration.between(LocalTime.of(13, 45, 10), LocalTime.of(13, 50, 10));

Duration d2 = Duration.between(instant1, instant2);

 

2. Period

날짜와 날짜 사이의 지속시간을 관리

Preiod d1 = Preiod.between(LocalDate.of(2017, 12, 01), LocalDate.of(2017, 12, 4));

 

 

날짜 조정, 파싱, 포메팅
LocalDate date1 = LocalDate.of(2017, 9, 21);

LocalDate date2 = date1.withYear(2011);

LocalDate date3 = date2.withDayOfMonth(25);

LocalDate date4 = date3.with(ChronoField.MONTH_OF_YEAR, 2);

LocalDate date5 = date4.plusWeeks(1);

LocalDate date6 = date5.minusWeeks(1);

 

 

TemporalAdjusters 사용하기

 

날짜를 보다 세부적이고 복잡하게 조정하고 변경할 수 있는 기능. TempralAdjuster 함수형 인터페이스가 제공되고 있어서 

LocalDate date = LocalDate.of(2014, 3, 18);

date = date.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));

date = date.with(TemporalAdjusters.lastDayOfMonth());

 

 

날짜와 시간 객체 출력과 파싱

 

DateTimeFormatter를 통해서 날짜나 시간을 특정한 형식의 문자열로 만들 수 있고 파싱할 수 있다. 

LocalDate date = LocalDate.of(2014, 3, 18);

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");

DateTimeFormatter italianFormatter = DateTimeFormatter.ofPattern("d. MMMM yyyy", Locale.ITALIAN);

System.out.println(date.format(DateTimeFormatter.ISO_LOCAL_DATE));

System.out.println(date.format(formatter));

System.out.println(date.format(italianFormatter));

LocalDate date2 = LocalDate.parse(date.format(formatter), italianFormatter);

 

 

시간대 적용하기

 

ZoneRules 클래스에는 약 40개 정도의 시간대를 포함하고 있다.

ZoneId romeZone = ZoneId.of("Europe/Rome");

ZoneDateTime zdt1 = date.atStartOfDay(romeZone);

ZoneDateTime zdt2 = date.atZone(romeZone);