[Java8] Chapter 5-1. Date와 Time (1)

 

✍️ 자바 8에 새로운 시간 API가 생긴 이유

자바8 이전에 사용했던 시간 관련 클래스 Date, Calendar가 여러모로 불편함을 유발했다. 

public static void main(String[] args) {
	Date date = new Date();
	Calendar calendar = new GregorianCalendar();
}

 

첫째로, 작명이 제대로 되어있지 않다. 클래스의 이름이 Date임에도 시간(Time)까지도 나타낼 수 있고 Time 스탬프도 찍을 수 있다.

Date date = new Date();
long time = date.getTime(); // Date(날짜)에서 time(시간)을 가져온다고?

심지어 getTime으로 가져오는 값이 현재의 시간이 아닌 1970.1.1로부터의 milliseconds를 반환한다.

/**
 * Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
 * represented by this {@code Date} object.
 *
 * @return  the number of milliseconds since January 1, 1970, 00:00:00 GMT
 *          represented by this date.
 */
public long getTime() {
    return getTimeImpl();
}

 

 

둘째로, Date 객체가 mutable 하다. 때문에 

메인 쓰레드를 3초 동안 재우고 다시 시간을 찍어보면 3초가 지난 시간이 찍힌다.

public static void main(String[] args) throws InterruptedException {
	Date date = new Date();
	long time = date.getTime();
	System.out.println(date);
	
	Thread.sleep(1000 * 3); // 3초 슬립
	
	Date after3Seconds = new Date();
	System.out.println(after3Seconds);
}

// Tue Feb 22 21:35:13 KST 2022
// Tue Feb 22 21:35:16 KST 2022

 

여기까지는 좋으나, setTime을 사용하면 객체의 시간 값을 변경할 수 있다.

public static void main(String[] args) throws InterruptedException {
	Date date = new Date();
	long time = date.getTime();
	System.out.println(date);
	
	Thread.sleep(1000 * 3); // 3초 슬립
	
	Date after3Seconds = new Date();
	System.out.println(after3Seconds);
	
	after3Seconds.setTime(time);
	System.out.println(after3Seconds);
}

// Tue Feb 22 21:38:16 KST 2022
// Tue Feb 22 21:38:19 KST 2022
// Tue Feb 22 21:38:16 KST 2022

 

이처럼 상태를 변경할 수 있는 객체mutable 객체

반대로 상태를 변경할 수 없는 객체immutable 객체라고 한다.

 

mutable 객체는 멀티 스레드 환경에서 안전하게 사용하기 어렵다.

 

 

셋째로, Type safety 하지 못해 버그가 발생할 확률이 높다. 

2022년 12월 25일을 그레고리안 캘린더로 인스턴스화하면 아래 코드일 것 같으나 이는 잘못된 코드이다.

public static void main(String[] args) throws InterruptedException {
	Calendar christmas2022 = new GregorianCalendar(2022, 12, 25);
}

 

월에 해당하는 month가 문제가 된다. 주석을 읽어보면 Month value is 0-based. e.g., 0 for January.  Month의 베이스 값은 0이다. 즉 1월은 0에 매치된다. 

/**
 * Constructs a {@code GregorianCalendar} with the given date set
 * in the default time zone with the default locale.
 *
 * @param year the value used to set the {@code YEAR} calendar field in the calendar.
 * @param month the value used to set the {@code MONTH} calendar field in the calendar.
 * Month value is 0-based. e.g., 0 for January.
 * @param dayOfMonth the value used to set the {@code DAY_OF_MONTH} calendar field in the calendar.
 */
public GregorianCalendar(int year, int month, int dayOfMonth) {
    this(year, month, dayOfMonth, 0, 0, 0, 0);
}

 

 

🍊 Date, Time 주요 API

  • 자바 8부턴 기계용 시간(machine time)인류용 시간(human time)으로 나눌 수 있다.
    • 기계용 시간은 EPOCK (1970년 1월 1일 0시 0분 0초)부터 현재까지의 타임스탬프를 표현한다.
    • 인류용 시간은 우리가 흔히 사용하는 연, 월, 일, 시, 분, 초 등을 표현한다.
  • 타임스탬프는 Instant를 사용한다.

  • 특정 날짜(LocalDate), 시간(LocalTime), 일시(LocalDateTime)를 사용할 수 있다.

  • 기간을 표현할 땐 Duration(시간 단위)Period(날짜 단위)를 사용할 수 있다.

  • DateTimeFormatter를 사용해서 시간을 특정한 문자열로 포맷팅할 수 있다.

 

 

 

본 내용은 백기선님의 자바8 강의 내용입니다.

 

더 자바, Java 8 - 인프런 | 강의

자바 8에 추가된 기능들은 자바가 제공하는 API는 물론이고 스프링 같은 제 3의 라이브러리 및 프레임워크에서도 널리 사용되고 있습니다. 이 시대의 자바 개발자라면 반드시 알아야 합니다. 이

www.inflearn.com