Java Date - 날짜와 시간 인터페이스

시간의 간격을 표현할 때 두 가지가 있었다.

시간의 개념 표현 방법 두 가지

  • 특정 시점의 시간(시각)
    • 프로젝트는 2026년 1월 1일까지 완료해야한다.
    • 다음 회의는 10시부터이다.
  • 시간 사이의 간격
    • 앞으로 2년은 공부해야한다.
    • 프로젝트 기간은 1년 남았다

시간을 표현할 때 어떠한 특정 시간이나 특정 시점의 간격이 있다.
자바로 핵심 인터페이스로 어떻게 구현하는지 먼저 그림부터 천천히 살펴보자.


특정 시간과 시간의 간격 구분하기

특정 시점의 시간

  • 특정 시점의 시간
    • Temporal (TemporalAccessor 포함) 인터페이스로 구현한다.
    • 구현에는 LocalDateTime, LocalDate, LocalTime, ZonedDateTime, OffsetDateTime, Instant 등으로 구성한다.

시간의 간격

  • 시간의 간격 (기간)
    • TemporalAmount 인터페이스로 구현한다.
    • 구현에는 Period, Duration 으로 구성한다.

TemporalAccessor 인터페이스

  • 날짜와 시간을 읽는 기본 인터페이스 (읽기 전용)
  • 특정 시점의 날짜와 시간 정보를 읽을 수 있는 최소한의 기능을 갖추고 있다.

Temporal 인터페이스

  • TemporalAccessor 하위 인터페이스로 날짜와 시간을 조작(추가 및 빼기 등) 기능을 제공. (읽기 쓰기)
    • 즉, 날짜와 시간 변경 및 조정 가능

TemporalAmount 인터페이스

  • 시간의 간격 (시간의 양 또는 기간)을 나타냄
  • 날짜와 시간 객체에 적용하고 그 객체를 조정한다.
  • 특정 날짜 부분에 일정 기간을 더하거나 빼기

시간 단위와 필드

날짜와 시간의 핵심 인터페이스로 시간의 단위를 뜻하는 TemporalUnit (ChronoUnit) 시간의 각 필드를 뜻하는 TemporalField(ChronoField) 이 있다.

  • TemporalUnit (ChronoUnit)
  • TemporalField(ChronoField)

TemporalUnit 인터페이스

  • TemporalUnit
    • 인터페이스는 날짜와 시간을 측정하는 단위로 나타냄
  • ChronoUnit
    • 구현체는 열거형으로 구현되어 있다.
    • 다양한 시간 단위를 갖고 있음
    • Unit 의 뜻은 단위로 시간의 단위 하나하나를 가리킨다.

ChronoUnit 시간 단위

ChronoUnit 설명
NANOS 나노초 단위
MICROS 마이크로초 단위
MILLS 밀리초 단위
SECONDS 초 단위
MINUTES 분 단위
HOURS 시간 단위

ChronoUnit 날짜 단위

ChronoUnit 설명
DAYS 일 단위
WEEKS 주 단위
MONTHS 월 단위
YEARS 년 단위
DECADES 10년 단위
CENTURIES 세기 단위
MILLENNIA 천년 단위

ChronoUnit 지원 메소드

메소드명 설명
between(Temporal, Temporal) Temporal 두 객체 사이의 시간을 ChronoUnit 단위로 측정하여 반환
isDateBased() 현재 ChronoUnit 날짜(년 월 주 일) 기반 단위인지 여부 반환
isTimeBased() 현재 ChronoUnit 시간(시 분 초) 기반 단위인지 여부 반환
isSupportedBy(Temporal) 주어진 Temporal 객체가 현재 Chrono 단위를인지 지원 여부 반환
getDuration() 현재 ChronoUnit의 기간을 Duration 객체로 반환

ChronoUnit 사용 예시

먼저 ChronoUnit 클래스를 살펴보면 다음과 같이 구성되어 있다.

public enum ChronoUnit implements TemporalUnit {
    NANOS("Nanos", Duration.ofNanos(1)),
    MICROS("Micros", Duration.ofNanos(1000)),
    MILLIS("Millis", Duration.ofNanos(1000_000)),
    SECONDS("Seconds", Duration.ofSeconds(1)),
    ....
}

앞서 설명한 것과 같이 구성되어 있음을 볼 수 있다.


ChronoUnit 내부의 단위 출력해보기

 ChronoUnit[] values = ChronoUnit.values();
for (ChronoUnit value : values) {
    System.out.println("value = " + value);
}

value = Nanos
value = Micros
value = Millis

ChronoUnit 내부의 단위들을 쭉 출력한 것을 볼 수 있다. toString 오버라이딩으로 인해 내부의 name 값들을 다 출력한 것이다.


ChronoUnit 특정 단위 출력해보기

System.out.println("MINITES: " + ChronoUnit.MINUTES);

MINITES: Minutes

특정 단위를 직접적으로 출력할 수 있다.


ChronoUnit 단위의 실제 값 출력 해보기

System.out.println("MINITES.duration: " + ChronoUnit.MINUTES.getDuration());
System.out.println("MINITES.duration(sec): " + ChronoUnit.MINUTES.getDuration().getSeconds());

MINITES.duration: PT1M
MINITES.duration(sec): 60

1분의 단위는 60초로 지정된 것을 볼 수 있다.


ChronoUnit - 날짜 차이 구하기

LocalTime lt1 = LocalTime.of(11, 0, 0);
LocalTime lt2 = LocalTime.of(13, 0, 0);

long secondsBetween = ChronoUnit.SECONDS.between(lt1, lt2);
System.out.println("secondsBetween = " + secondsBetween);
long minitesBetween = ChronoUnit.MINUTES.between(lt1, lt2);
System.out.println("minitesBetween = " + minitesBetween);

secondsBetween = 7200
minitesBetween = 120

ChronoUnit 사용한 날짜의 차이를 구할 때 사용한다.


TemporalField 인터페이스

ChronoField 날짜 및 시간의 열거형을 나타낸다. 다양한 필드를 통해 날짜의 시간의 특정 부분을 나타내고 있다. 연도, 월, 일, 시간, 분이 포함된다.

  • TemporalField
    • 인터페이스는 날짜와 시간을 나타낸다.
    • 구현체는 ㅈChronoField 열거형으로 구현
  • ChronoField 클래스는 다양한 필드를 통해 특정 날짜를 가르키고 있다.
  • 필드(Field) 뜻은 날짜와 시간 중에 있는 특정 필드를 뜻한다.
    • 예 2025년 5월 15일의 필드는 각각 다음과 같다.
      • YEAR 2025
      • MONTH_OF_YEAR 5
      • DAY_OF_MONTH 15
  • 단순 시간으로 쪼갠 ChronoUnit 과 다른 것을 살펴 볼 수 있다.
  • ChronoField 사용하여 날짜와 시간 각 필드의 원하는 데이터를 조회할 수 있도록 한다.

ChronoField 연도 관련 필드

필드 이름 설명
ERA 연대, 서기(AD) 기원전(BC)
YEAR_OF_ERA 연대 내의 연도
YEAR 연도
EPOCH_DAY 1970-01-01 부터의 일 수

ChronoField 월 관련 필드

필드 이름 설명
MONTH_OF_YEAR 월 (1월 = 1)
PROLEPTIC_MONTH 연도를 월로 확장한 값

ChronoField 주, 일 관련 코드

필드 이름 설명
DAY_OF_WEEK 요일 (월요일 = 1)
ALIGEND_DAY_OF_WEEK_IN_MONTH 월의 첫 번째 요일 기준으로 정렬한 요일
ALIGEND_DAY_OF_WEEK_IN_YEAR 연의 첫 번째 요일 기준으로 정렬한 요일
DAY_OF_MONTH 월의 일(1일 = 1)
DAY_OF_YEAR 연의 일(1월 1일 = 1)
EPOCH_DAY 1970-01-01 부터의 일 수

ChronoField 시간 관련 필드

필드 이름 설명
HOUR_OF_DAY 시간 (0-23)
CLOCK_HOUR_OF_DAY 시계 시간(1-24)
HOUR_OF_AMPM 오전 / 오후 시간 (0-11)
CLOCK_HOUR_OF_AMPM 오전 / 오후 시계 시간 (1-12)
MINUTE_OF_HOUR 분 (0-59)
SECOND_OF_MINUTE 초 (0-59)
NANO_OF_SECOND 초의 나노초 (0-999,999,999)
MICRO_OF_SECOND 초의 마이크로초(0-999,999)
MILLI_OF_SECOND 초의 밀리초(0-999)

ChronoField 기타 필드

필드 이름 설명
AMPM_OF_DAY 하루의 AM/PM 부분
INSTANT_SECONDS 초를 기준으로 한 시간
OFFSET_SECONDS UTC/GMT 시간 오프셋 초

ChronoField 지원 메소드

필드 이름 반환 타입 설명
getBaseUnit() TemporalUnit 필드의 기본 단위를 반환. 필드의 기본 단위: ChronoUnit.MINUTES
getRangeUnit() TemporalUnit 필드의 범위 단위를 반환. MONTH_OF_YEAR 범위의 단위: ChronoUnit.YEARS
isDateBased() boolean 주로 날짜 기반으로 하는지 여부 확인. YEAR, MONTH, DAY 와 같은 날짜 필드인 경우 true
isTimeBased() boolean 주로 시간 기반으로 하는지 여부 확인. HOUR_OF_DAY 와 같은 날짜 필드인 경우 true
range() ValueRange 필드가 가질 수 있는 유효 범위로 ValueRange 객체로 반환. 이 객체는 최소값과 최대값을 제공한다.

ChronoField range - 필드 범위 출력하기

ChronoField[] values = ChronoField.values();
for (ChronoField value : values) {
    System.out.println(value + ", range = " + value.range());

}

...
HourOfDay, range = 0 - 23
ClockHourOfDay, range = 1 - 24
AmPmOfDay, range = 0 - 1
DayOfWeek, range = 1 - 7
...

크로노 필드를 살펴보면 필드들이 있고 숫자의 레인지 범위를 나타내고 있다.


ChronoField.MONTH_OF_YEAR 범위 출력해보기

System.out.println("MONTH_OF_YEAR.range() " + ChronoField.MONTH_OF_YEAR.range());

MONTH_OF_YEAR.range() 1 - 12

MONTH_OF_YEAR 는 1~12 범위의 값을 갖고 있다.

System.out.println("DAY_OF_MONTH.range() " + ChronoField.DAY_OF_MONTH.range());

DAY_OF_MONTH.range() 1 - 28/31

한달의 범위는 1 ~ 28/31 범위를 갖고 있다. 이는 2월이 28일인 경우가 있어서 그렇다.


정리

두 TemporalUnit, TemporalField 인터페이스와 구현체를 함께 살펴보았다.
단독으로 사용보다는 날짜와 시간을 조회 및 조작에 사용된다.