자바 날짜와 시간 라이브러리 총정리

2025. 7. 7. 18:22·🌱 인프런/☕️ 김영한의 실전 자바 - 중급 1편

☕️  김영한의 실전 자바 - 중급 1편 을 듣고 작성하는 복습 블로그 입니다.

 

0. 배경

프로그램을 개발하다보면 📅 날짜와 🕰️ 시간 관련된 기능을 구현해야할 일이 자주 생긴다.

 

예를 들어서

💰 정산 프로그램을 개발할 경우 특정 시점 사이의 정산 데이터를 가져와야 하고

👆일반적인 데이터 조회에서도 사용자가 원하는 날짜를 지정해서 검색할 수 있어야 한다.

 

자바에는 날짜와 시간 관련된 여러 라이브러리가 존재하는데, 이번에 라이브러리에 대해서 알아보자

 


1.  날짜와 시간 라이브러리가 필요한 이유

💬 "굳이 날짜와 시간 라이브러리가 필요할까 ?"

💬 "그냥 내가 하나하나 계산하면 되지 않을까 ?" 라고 생각할 수 있다.

하지만, 날짜와 시간을 그냥 계산하기엔 고려해야할 요소들이 많다.

 

1. 🌎 윤년

지구가 태양을 한 바퀴 도는데 평균 365.425일이 걸린다.

정확히 365일이 아니기 때문에 나머지 0.425일을 더해서 약 4년마다 하루를 추가하는 윤년을 사용한다

 

2. ☀️ 일광 절약 시간

썸머타임이라고도 한다.

국가나 지역에 다라 적용 여부와 시작 및 종료 날짜가 다르기 때문에 나라별로 1시간 오차가 발생할 수 있다.

 

3. 🕰️ 타임존

나라마다 다양한 타임존으로 나뉘어져 있다.

각 타임존은 UTC 로부터의 시간 차이로 정의된다.

 

이런 날짜와 시간 다양한 것들을 모두 반영하기엔 혼자 개발해서는 어렵다 

→ 그렇기 때문에 잘 설계된 라이브러리를 사용해야 한다.


2. 자바 날짜와 시간 라이브러리

https://docs.oracle.com/javase/tutorial/datetime/iso/overview.html

 

오라클의 자바 document 에 날짜와 시간 관련 라이브러리에 대해서 정리된 표가 있다

간단하게 설명하자면 다음과 같다

라이브러리 명 설명 형식
LocalDate 날짜만 표현할 때 사용 2013-12-21
LocalTime 시간만 표현할 때 사용 08:20:30.213
LocalDateTime 날짜 + 시간을 표현할 때 사용 2013-12-21T08:20:30.213
ZonedDateTime 시간대를 고려한 날짜와 시간을 표현 (+ 타임존 포함) 2013-11-21T08:20:30.213+9:00[Asia/Seoul]
OffsetDateTime 시간대를 고려한 날짜와 시간을 표현 (+ 타임존 미포함) 2013-11-21T08:20:30.213+9:00
Instance UTC를 기준으로 하는 시간의 한 지점  
Period 두 날짜 사이의 간격 (년 / 월 / 일)  
Duration 두 시간 사이의 간격 (시 / 분 / 초)  

 


3. LocalDate, LocalTime, LocalDateTime

💡 시간대를 고려하지 않고, 날짜와 시간을 계산하는 경우 사용

 

LocalDate, LocalTime, LocalDateTime 모두 앞에 Local 이 붙는다.

🙅‍♀️이는 세계 시간대를 고려하지 않는다는 의미로, 타임존이 적용되지 않는다.

 

 

LocalDate : 날짜

LocalDate now = LocalDate.now();
LocalDate ofDate = LocalDate.of(2025, 7, 7);
LocalDate ofDatePlus10 = ofDate.plusDays(10);

System.out.println("now = " + now);
System.out.println("ofDate = " + ofDate);
System.out.println("ofDatePlus10 = " + ofDatePlus10);
now = 2025-07-07
ofDate = 2025-07-07
ofDatePlus10 = 2025-07-17

 

  • now() : 현재 날짜를 기준으로 LocalDate 를 생성한다 
  • of(년, 월, 일) : 특정 날짜를 기준으로 LocalDate 를 생성한다.
  • plusDays(일) : 일을 더한다

 

 

 

LocalTime : 시간

LocalTime now = LocalTime.now();
LocalTime ofTime = LocalTime.of(12, 0, 0);
LocalTime ofTimePlusHour = ofTime.plusHours(10);

System.out.println("now = " + now);
System.out.println("ofTime = " + ofTime);
System.out.println("ofTimePlusHour = " + ofTimePlusHour);
now = 17:14:28.122669
ofTime = 12:00
ofTimePlusHour = 22:00
  • now() : 현재 시간을 기준으로 LocalTime 를 생성한다 
  • of(시간, 분, 초) : 특정 시간을 기준으로 LocalTime 를 생성한다.
  • plusHours(시간) : 시간을 더한다

 

 

 

 

LocalDateTime : 날짜 + 시간

LocalDateTime now = LocalDateTime.now();
LocalDateTime ofDateTime = LocalDateTime.of(2025, 7, 7, 12, 0, 0);

LocalDateTime ofDateTimePlusDays = ofDateTime.plusDays(10);
LocalDateTime ofDateTimePlusHours = ofDateTime.plusHours(10);

System.out.println("now = " + now);
System.out.println("ofDateTime = " + ofDateTime);
System.out.println("ofDateTimePlusDays = " + ofDateTimePlusDays);
System.out.println("ofDateTimePlusHours = " + ofDateTimePlusHours);
now = 2025-07-07T17:17:33.380426
ofDateTime = 2025-07-07T12:00
ofDateTimePlusDays = 2025-07-17T12:00
ofDateTimePlusHours = 2025-07-07T22:00
  • now() : 현재 날짜, 시간을 기준으로  LocalDateTime 를 생성한다 
  • of(년, 월, 일, 시간, 분, 초) : 특정 날짜, 시간 을 기준으로 LocalDateTime 를 생성한다.
  • plusHours(시간) : 시간을 더한다
  • plusDays(일) : 일을 더한다

→ LocalDateTime 은 시간과 날짜를 모두 가지기 때문에 plusHours, plusDays 를 사용할 수 있다

 


4. ZonedDateTime, OffsetDateTime

💡 타임존을 고려한 날짜와 시간을 사용해야 하는 경우 

 

ZonedDateTime은 다른 나라와의 타임존을 고려한다.

자바에서 타임존은 ZoneId 로 제공된다.

 

ZoneId

for (String availableZoneId : ZoneId.getAvailableZoneIds()) {
    System.out.println(availableZoneId);
}

System.out.println("ZoneId.systemDefault = " + ZoneId.systemDefault());
System.out.println("ZoneId.of = " + ZoneId.of("Asia/Seoul"));
  • ZoneId.systemDefault() : 시스템이 사용하는 기본 ZoneId 를 반환한다
  • ZoneId.of() : 입력된 타임존에 해당하는 ZoneId 를 반환한다
  • ZoneId.getAvailableZoneIds() : 사용가능한 모든 ZoneId 를 반환한다 
  • DST (서머 타임) 정보를 포함한다.

 

ZonedDateTime

public final class ZonedDateTime implements Temporal, ChronoZonedDateTime<LocalDate>, Serializable {        
    private final LocalDateTime dateTime;
    private final ZoneOffset offset;
    private final ZoneId zone;
}

 

  • ZonedDateTime 은 내부에 LocalDateTime, ZoneOffset, ZoneId 가 있다
  • 날짜와 시간을 나타내는 LocalDateTime 에 시간대를 표현하는 타임존이 포함된다.
ZonedDateTime zdt1 = ZonedDateTime.now();
System.out.println("zdt1 = " + zdt1);

ZonedDateTime zdt2 = ZonedDateTime.of(2030, 1, 1, 13, 30, 50, 0, ZoneId.of("Asia/Seoul"));
System.out.println("zdt2 = " + zdt2);

ZonedDateTime utcZdt = zdt2.withZoneSameInstant(ZoneId.of("UTC"));
System.out.println("utcZdt = " + utcZdt);
zdt1 = 2025-07-07T17:37:36.873016+09:00[Asia/Seoul]
zdt2 = 2030-01-01T13:30:50+09:00[Asia/Seoul]
utcZdt = 2030-01-01T04:30:50Z[UTC]
  • now() : 현재 날짜와 시간으로 생성, 타임존은 시스템 시간으로 들어간다
  • of() : 특정 날짜와 시간을 기준으로 생성, ZoneId 를 지정할 수 있다
  • withZoneSameInstance(ZoneId) : 해당 시간의 타임존을 변경할 수 있다

 

OffsetDateTime

public final class OffsetDateTime implements Temporal, TemporalAdjuster, Comparable<OffsetDateTime>, Serializable {
    private final LocalDateTime dateTime;
    private final ZoneOffset offset;
}
  • LocalDateTime 에 ZoneOffset 만 추가되어 있다
  • ZoneId 가 없기 떄문에 타임존을 계산할 수 없다
ZoneOffset

UTC 기준의 고정된 시간 차이를 나타낸다 ex) "+09:00", "-05:00" 등
서머타임 (DST) 를 고려하지 않는다

OffsetDateTime nowOdt = OffsetDateTime.now();
System.out.println("nowOdt = " + nowOdt);

OffsetDateTime odt = OffsetDateTime.of(LocalDateTime.of(2030, 1, 1, 13, 30, 50), ZoneOffset.of("+01:00"));
System.out.println("odt = " + odt);
nowOdt = 2025-07-07T17:55:54.615875+09:00
odt = 2030-01-01T13:30:50+01:00
  • now() : 현재 날짜와 시간으로 생성
  • of() : 특정 날짜와 시간을 기준으로 생성, Zoneoffset 을 지정할 수 있다

5. Instant

💡 시간대 변환 없이 시간 계산이 필요할 때 
public final class Instant implements Temporal, TemporalAdjuster, Comparable<Instant>, Serializable {
    private final long seconds;
    private final int nanos;
}
  • 내부적으로 초와 나노초만 가지고 있다
  • 1970년 1월 일 0시 0분 0초를 기준으로 경과한 시간을 가진다
  • UTC 를 기준으로 하기 때문에 시간대에 영향을 주지 않는다
  • 사람이 읽고 이해하기에는 직관적이지 않다

 

사용

  1. 전세계적인 시간 기준이 필요할 때 
  2. 시간대 변환 없이 시간 계산이 필요할 때 
  3. 데이터 저장 및 교환

에 사용된다.

 

Instant now = Instant.now(); // UTC 기준
System.out.println("now = " + now);
now = 2025-07-07T08:59:50.508822Z

 

초가 들어있지만 출력할 때는 날짜 형식에 맞춰서 출력되는데

@Override
public String toString() {
    return DateTimeFormatter.ISO_INSTANT.format(this);
}

Instant 클래스 내부에서 toString() 을 오버라이딩 하기 때문이다


6. Duration, Period

💡 두 날짜 사이의 간격이나 시간 사이의 간격을 나타낼 때 

Period 는 두 날짜 사이의 간격을 년 / 월 / 일 단위로 나타낸다

// 생성
Period period = Period.ofDays(10);
System.out.println("period = " + period);

// 계산에 사용
LocalDate plusDate = LocalDate.of(2030, 1, 1).plus(period);
System.out.println("plusDate = " + plusDate);

// 기간 차이
Period between = Period.between(LocalDate.of(2023, 1, 1), LocalDate.of(2023, 4, 2));
System.out.println("기간: " + between.getMonths() + "개월 " + between.getDays() + "일");
  • ofXXX() : 특정 기간을 지정해서 Period 를 생성
  • plus(Period period): 특정 날짜에 기간을 더할 수 있다
  • between(startDate, endDate) : 특정 날짜의 차이를 구할 수 있다

 

Duration 은 두 시간 사이의 간격을 시 / 분 / 초 단위로 나타낸다

// 생성
Duration duration = Duration.ofMinutes(30);
System.out.println("duration = " + duration);

// 계산
LocalTime plusTime = LocalTime.of(1, 0).plus(duration);
System.out.println("더한 시간: " + plusTime);

// 시간 차이
Duration between = Duration.between(LocalTime.of(9, 0), LocalTime.of(10, 0));
System.out.println("차이 : " + between.getSeconds() + "초");
System.out.println("근무 시간: " + between.toHours() + "시간 " + between.toMinutesPart() + "분");
  • ofXXX() : 특정 시간을 지정해서 Period 생성
  • plus() : LocalTime 에 Period 를 더할 수 있다
  • between() : LocalTime간의 차리를 구할 수 있다
  • toMinutes() : 전체 분
  • toMinutesPart() : 시간을 빼고 난 후의 분

 

7. 날짜와 시간 핵심 인터페이스

날짜와 시간은 특정 시점과 간격으로 나눌 수 있다. 

  • 특정 시점 : 내 생일은 2월 7일이야 
  • 시간의 간격 : 내 생일까지 3일 남았어

 

특정 시점을 나타내는 클래스는 앞에서 살펴봤던

  • LocalDateTime
  • ZonedDateTime
  • Instance 

가 있고, 각 클래스는 Temporal 인터페이스를 구현하고, Temporal 인터페이스는 TemporalAccessor 를 상속받는다

 

 

시간의 간격을 나타내는 클래스는

  • Period
  • Duration

이 있고, 각 클래스는 TemporalAmount 인터페이스를 구현한다.


8. 시간의 단위와 시간 필드

시간의 단위 - ChronoUnit

  • 위와 같이 시간 단위 / 날짜 단위 / 기타 단위 별로 다양한 ChronoUnit 을 가진다.
  • TemporalUnit 인터페이스를 구현한다
LocalTime lt1 = LocalTime.of(1, 10, 0);
LocalTime lt2 = LocalTime.of(1, 20, 0);

long secondsBetween = ChronoUnit.SECONDS.between(lt1, lt2);
System.out.println("secondsBetween = " + secondsBetween);
  • 두 날짜 / 시간 차이를 원하는 단위로 쉽게 계산할 수 있다

 

시간 필드- ChronoField

  • 날짜와 시간의 특정 부분을 나타내는 데 사용되는 열거형
  • 날짜와 시간의 각 필드 중에서 원하는 데이터를 조회할 수 있다
LocalDateTime dt = LocalDateTime.of(2030, 1, 1, 13, 30, 59);
System.out.println("YEAR = " + dt.get(ChronoField.YEAR));
System.out.println("YEAR = " + dt.getYear());

LocalDateTime changedDt1 = dt.with(ChronoField.YEAR, 2020);
LocalDateTime changedDt2 = dt.withYear(2020);

LocalDateTime with = dt.with(TemporalAdjusters.next(DayOfWeek.FRIDAY));

9. 문자열 파싱과 포맷팅

포맷팅 : 날짜와 시간 데이터를 원하는 포맷의 문자열로 변경 (Date→String)

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일");
String formattedDate = date.format(formatter);
System.out.println("날짜와 시간 포맷팅 = " + formattedDate);

 

 

파싱 : 문자열을 날짜와 시간 데이터로 변경 (String→ Date)

String input = "2030년 01월 01일";
LocalDate parseDate = LocalDate.parse(input, formatter);
System.out.println("문자열 파싱 날짜와 시간: " + parseDate);

'🌱 인프런 > ☕️ 김영한의 실전 자바 - 중급 1편' 카테고리의 다른 글

자바 Object 클래스  (1) 2025.09.01
자바 래퍼, Class 총정리  (0) 2025.07.19
자바 예외처리 총정리  (1) 2025.07.11
자바 열거형 ENUM 총정리  (2) 2025.07.10
자바 중첩 클래스와 내부 클래스  (3) 2025.07.09
'🌱 인프런/☕️ 김영한의 실전 자바 - 중급 1편' 카테고리의 다른 글
  • 자바 래퍼, Class 총정리
  • 자바 예외처리 총정리
  • 자바 열거형 ENUM 총정리
  • 자바 중첩 클래스와 내부 클래스
말린
말린
  • 말린
    개발새발
    말린
  • 전체
    오늘
    어제
    • 분류 전체보기 (58)
      • 👩🏻‍💻 알고리즘 (17)
        • 백준 (17)
      • ✒️ 글또 10기 (6)
      • 🗃️ 데이터베이스 (5)
      • ☕️ 자바 (1)
      • 🌱 인프런 (28)
        • ⚓ 쿠버네티스 어나더 클래스 (지상편) (22)
        • ☕️ 김영한의 실전 자바 - 중급 1편 (6)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
말린
자바 날짜와 시간 라이브러리 총정리
상단으로

티스토리툴바