Java 날짜 - Date-Time API
개요
JavaSE 8부터는 날짜/시간을 다루는 새로운 API로 Date and Time API가 도입되었다. Date-Time API는 java.time
패키지에 포함되어 있다.
java.time
패키지로 제공되는 주요 클래스는 아래와 같다.
LocalDateTime
/LocalDate
/LocalTime
: 시차 정보가 없는 로컬 일시OffsetDateTime
/OffsetTime
: 시차 정보가 있는 날짜와 시간ZonedDateTime
: 타임존와 지역을 기반으로 한 정보(서머 타임 등)가 있는 날짜와 시간
일반적으로는 시차 정보를 필요로 하지 않는 경우에는 Local~클래스를 사용하고, 그렇지 않으면 Zoned~클래스를 하는 식으로 구분된다. 그리고 Offset~클래스를 이용하는 것은 별로 없을까 생각된다.
LocalDateTime
의 now
/of
/parse
메서드
now
/of
/parse
메서드는 문자열에서 날짜/시간 값을 생성한다.
public static LocalDateTime now()
public static LocalDateTime of(int year, int month, int day, int hour, int minute [,int second [,int nano]])
public static LocalDate parse(CharSequence text)
year: 년
month: 달
day: 일
hour: 때
minute:분
second:초
nano: 나노초
text: 날짜 시간 문자열
java.time
패키지에서는 목적에 따라 Local/Offset/Zoned 계열 클래스가 준비되어 있는데, 이 메소드들은 생성하는 방법은 동일하다.
먼저 현재 시간을 표시하려면 now
메서드를 사용한다.
of
메서드는 연월일/시분초를 지정하여 객체를 생성한다. parse
메소드를 사용하여 일자 시각 캐릭터 라인으로부터 객체를 생성할 수도 있다.
package com.devkuma.basic.datetime;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
public class TimeCreate {
public static void main(String[] args) {
LocalDateTime local = LocalDateTime.now();
System.out.println(local);
// 결과: 2022-09-05T12:03:34.123041
OffsetDateTime offset = OffsetDateTime.of(
2022, 9, 5, 12, 3, 29, 0, ZoneOffset.of("+09:00"));
System.out.println(offset);
// 결과: 2022-09-05T12:03:29+09:00
ZonedDateTime zoned = ZonedDateTime.parse("2022-09-05T12:03:29+09:00[Asia/Seoul]");
System.out.println(zoned);
// 결과: 2022-09-05T12:03:29+09:00[Asia/Seoul]
}
}
실행 결과:
false
false
true
각 객체에서 다음 메서드를 사용하여, 각각의 날짜/시간 요소에 액세스할 수도 있다.
각각의 날짜/시간 요소에 액세스하는 메소드
메소드 | 개요 |
---|---|
getYear |
년 |
getMonth |
월(Month 타입) |
getMonthValue |
월(1~12) |
getDayOfMonth |
일 |
getDayOfWeek |
요일 |
getDayOfYear |
연간 통산일 |
getHour |
시간 |
getMinute |
분 |
getSecond |
초 |
getNano |
나노초 |
between 메서드
between
메서드는 날짜/시간 값의 차이 구한다.
public static Period between(LocalDate start, LocalDate end) // Period
public static Duration between(Temporal start, Temporal end) // Duration
start: 시작일시
end: 종료일시
Period/Duration#between
메서드를 사용하여, 일자 시각 객체간의 시간차를 구할 수가 있다. Period
는 날짜 간격을 나타내고, Duration
은 시간 간격을 나타내는 객체이다
- Temporal 클래스는 Local/Offset/Zonedr 계열 클래스 모든 인터페이스이다.
다음은 미리 준비한 2개의 날짜/시간의 차이를 Period/Duration#between
메서드로 구하는 예제이다.
TimeBetween.java
package com.devkuma.basic.datetime;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.Period;
public class TimeBetween {
public static void main(String[] args) {
LocalDateTime local1 = LocalDateTime.of(
2021, 1, 1, 3, 30, 0, 0);
LocalDateTime local2 = LocalDateTime.of(
2022, 9, 5, 12, 14, 30, 0);
System.out.println(local1); // 결과: 2021-01-01T03:30
System.out.println(local2); // 결과: 2022-09-05T12:14:30
Period period = Period.between(local1.toLocalDate(), local2.toLocalDate());
System.out.println("날짜 차이: " + period); // 결과: 날짜 차이: P1Y8M4D
System.out.println("날짜 차이: " +
period.getYears() + "년 " + period.getMonths() + "월 " +
period.getDays() + "일"); // 결과: 날짜 차이: 1년 8월 4일
Duration duration = Duration.between(local1, local2);
System.out.println("시간 차이: " + duration);
// 결과: 시간 차이: PT14696H44M30S
System.out.println("시간 차이: " + duration.toHours() + "시간");
// 결과: 시간 차이: 14696시간
System.out.println("시간 차이: " + duration.toMinutes() + "분");
// 결과: 시간 차이: 881804분
System.out.println("시간 차이: " + duration.getSeconds() + "초");
// 결과: 시간 차이: 52908270초
}
}
실행 결과:
2021-01-01T03:30
2022-09-05T12:14:30
날짜 차이: P1Y8M4D
날짜 차이: 1년 8월 4일
시간 차이: PT14696H44M30S
시간 차이: 14696시간
시간 차이: 881804분
시간 차이: 52908270초
Period/Duration
객체로 부터 일 수나 시간 수를 구하려면, 다음과 같은 메서드를 이용한다.
Period/Duration 클래스의 주요 메서드
클래스 | 메서드 | 개요 |
---|---|---|
Period | getYears | 년수 |
getMonths | 월수 | |
getMonths | 월수 | |
Duration | toDays | 일수 |
toHours | 시간 수 | |
toMinutes | 분수 | |
toMillis | 밀리초 수 | |
toNanos | 나노초 수 |
날짜 및 시간 데이터 계산
public LocalDateTime plus(long value, TemporalUnit unit)
public LocalDateTime minus(long value, TemporalUnit unit)
value: 증감분
unit: 단위
plus/minus
메서드를 사용하여, 일자 시각 요소를 더하고 뺄수 있다. 인수 unit
는 TemporalUnit
인터페이스의 구현 클래스인 ChronoUnit
의 상수로 추가 혹은 빼려는 단위를 지정한다.
TemporalUnit 인터페이스의 주요 상수
상수 | 개요 |
---|---|
YEARS | 년 |
MONTHS | 달 |
DAYS | 일 |
WEEKS | 주 |
HOURS | 시간 |
MINUTES | 분 |
SECONDS | 초 |
MILLIS | 밀리 |
NANOS | 나노초 |
다음은 미리 준비한 날짜에 대해, 3개월 후 10일 전의 날짜를 구하는 예제이다.
package com.devkuma.basic.datetime;
import java.time.LocalDateTime;
public class TimePlus {
public static void main(String[] args) {
LocalDateTime local = LocalDateTime.parse("2022-09-05T12:30");
System.out.println(local); // 결과: 2022-09-05T12:30
System.out.println(local.plusMonths(3)); // 결과: 2022-12-05T12:30
System.out.println(local.minusDays(10)); // 결과: 2022-08-26T12:30
}
}
실행 결과:
2022-09-05T12:30
2022-12-05T12:30
2022-08-26T12:30
또한, plus/minus 메서드에는 각각의 일자/시각 요소에 특화된 메소드가 다음과 같이 있다.
날짜/시간을 가산/감산하는 방법
메서드 | 개요 |
---|---|
plusYears/minusYears | 년 |
plusMonths/minusMonths | 월 |
plusDays/minusDays | 일 |
plusWeeks/minusWeeks | 주수 |
plusHours/minusHours | 시간 |
plusMinutes/minusMinutes | 분 |
plusSeconds/minusSeconds | 초 |
plusNanos/minusNanos | 나노초 |
Date/Calendar 클래스에서 DateTime-API 클래스로 상호 변환
public static Date from(Instant instant) // Date
public Instant toInstant() // Date/Calendar
public static LocalDateTime ofInstant(Instant instant, ZoneId zone) // XxxxxDateTime
instant: 변환할 인스턴트
새롭게 Date-Time API가 도입되었다고 해도, 갑자기 모든 코드를 Date-Time API로 통일하는 것은 현실적으로 쉽지 않다. 당분간은, 기존에 java.util
패키지와 병행하게 될 것이다. 그래서 기존의 Date/Calendar 클래스에 Date-Time API와 상호 변환하기 위한 메소드를 제공하고 있다.
Date#from
메서드는 주어진 Instant
객체에서 Date
객체를 생성한다. Instant
는 날짜 시간을 1970년 1월 1일 이후의 경과 시간으로 유지하는 클래스이다. Date-Time API의 날짜/시간 클래스는 각각 toInstant
메소드를 제공하고 있어서 Instant
객체를 생성할 수 있게 되어 있으므로, 이를 from
메소드에 건네주면 Date
객체를 생성할 수 있다.
Calendar
클래스에는Date#from
메서드에 해당하는 메서드는 없다. 생성된Date
객체로부터Calendar
객체를 생성하게 된다.
Calendar/Date
클래스에도 toInstant
메소드는 제공하고 있다. 생성된 Instant
객체를 LocalDateTime
/OffsetDateTime
/ZonedDateTime
클래스의 ofInstant
메서드에 전달하여 각각 해당 객체를 생성할 수 있다.
다음은 LocalDateTime
객체를 Date
객체로, Calendar
객체를 LocalDateTime
객체로 변환하는 예제이다.
package com.devkuma.basic.datetime;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.Calendar;
import java.util.Date;
public class TimeTrans {
public static void main(String[] args) {
LocalDateTime local = LocalDateTime.now();
System.out.println(local); // 결과: 2022-09-05T14:32:05.526238
Instant instant = local.toInstant(ZoneOffset.of("+09:00"));
Date date = Date.from(instant);
System.out.println(date); // 결과: Mon Sep 05 14:32:05 KST 2022
Calendar cal = Calendar.getInstance();
Instant instant2 = cal.toInstant();
LocalDateTime local2 = LocalDateTime.ofInstant(instant2, ZoneId.of("Asia/Seoul"));
System.out.println(local2); // 결과: 2022-09-05T14:32:05.542
}
}
실행 결과:
2022-09-05T14:32:05.526238
Mon Sep 05 14:32:05 KST 2022
2022-09-05T14:32:05.542
String에서 LocalDate
/LocalDateTime
으로 변환하는 방법
String
을 java.time.LocalDate
로 변환은 LocalDate.parse
와 DateTimeFormatter
를 이용하여 날짜 문자열을 변환한다.
String
을 java.time.LocalDateTime
로 변환은 문자열을 LocalDate
로 만들고, LocalTime
와 같이 인자로 받아서 생성한다.
package com.devkuma.basic.datetime;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
public class StringConvent {
public static void main(String[] args) {
String strDate = "2022/12/12";
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
LocalDate localDate = LocalDate.parse(strDate, dateTimeFormatter);
System.out.println(localDate);
LocalDateTime ldt = LocalDateTime.of(localDate, LocalTime.of(0, 0));
System.out.println(ldt);
}
}
실행 결과:
2022-12-12
2022-12-12T00:00
날짜 문자열이 2022/12/12
와 같은 형식이면, Format
지정은 DateTimeFormatter.ISO_DATE
로 대체 할 수 있다. DateTimeFormatter.ISO_DATE
는 yyyy-mm-dd
를 상수로 선언한다.