자바에서 시간이나 날짜를 다뤄야하는 일이 있다면 가장 먼저 구글에 자바 현재 시간
과 같은 형식으로 검색을 할 것 같습니다.
그럼 다수의 블로그들이 calendar
클래스나 date
클래스를 사용하여 설명하고 있을 겁니다.
자바 8 이하의 버전을 사용하고 있다면 사용해야겠지만 대부분 자바 8 정도는 사용하고 있기 때문에 자바 8 부터 사용하고 있는 java.time
패키지를 사용하는 것이 바람직하다.
java.time
패키지를 사용해야 하는 이유그렇다면 왜 java.time
패키지를 사용해야 하는가?
자바 8 이전의
[util.Date](http://util.Date)
클래스는 변하기 쉬운( mutable ) 클래스이기 때문에 스레드 안전 ( thread safe ) 하지 않습니다.
변하기 쉬우면 좋은거 아닌가? 라고 생각할 수도 있습니다.
아주 간단한 프로그램이라면 상관없을 수도 있지만 규모가 있거나 어플리케이션에서는 스레드 안전하다는 것은 굉장히 중요합니다.
여러 작업이 동작하면서 내가 예상치 못하게 다른 스레드에서 그 값을 수정하여 다른 값이 전달될 가능성이 있기 때문에 java.time
패키지의 클래스들을 사용해야 합니다.
버그가 발생할 여지가 많습니다. 타입 안정성이 없고, 월이 0 부터 시작하는 등의 불편함을 가지고 있습니다.
Calendar birthDay = new GregorianCalendar( 2022, 12, 25 );
birthDay.getTime(); // Wed Jan 25 00:00:00 GMT 2023
위의 코드를 입력한 개발자는 2022 년 12 월 25 일의 날짜 객체를 원했겠지만 실제로 얻은 날짜는 2023년 1월 25일이라는 결과다. 이렇듯 사용하기에 불편한 점이 많다.
java.time
패키지자바 8 버전에서 공개된
java.time
패키지에는 다음과 같은 클래스들을 제공하고 있다.
Instant
: 타임스탬프 ( 기계용 시간, EPOCH )
LocalDate
: 시간이 없는 날짜 ( 타임존에 대한 참조가 없음 )
LocalTime
: 날짜가 없는 시간 ( 타임존에 대한 참조가 없음 )
LocalDateTime
: 날짜와 시간을 결합한 클래스
ZonedDateTime
: UTC 에서 시간대 및 타임존에 대한 참조를 가진 시간과 날짜를 다루는 클래스
그 중 날짜를 다룰 때 쓰이는 LocalDate
클래스에 대해서 먼저 알아보도록 하자.
기본적으로 java.time
패키지의 클래스들은 불변 클래스이기 때문에 한번 생성되면 내부 필드값을 바꿀 수 없기 때문에 public
생성자를 제공하지 않는다.
LocalDate
// 현재 날의 객체 얻기
LocalDate localDate = LocalDate.now(); // 2022-12-25
// 특정 일자의 날짜 가져오는 정적 메소드
LocalDate localDate = LocalDate.of( 2022, 12, 25 );
💡
LocalDate.parse
은 기본적으로yyyy-MM-dd
형식을 기준으로 날짜 정보를 가져오며DateTimeFormatter
를 설정하여 다른 형식을 사용할 수 있다.
// LocalDate -> String
LocalDate.of( 2022, 12, 12 ).format( DateTimeFormatter.BASIC_ISO_DATE); // 20221212
// String -> LocalDate
LocalDate.parse( "20221212", DateTimeFormatter.BASIC_ISO_DATE); // 2022-12-12
LocalDate localDate = LocalDate.parse( "2022-12-25" ); // 2022-12-25
// LocalDate -> java.sql.Date
Date.valueOf( LocalDate.of( 2022, 12, 12 ) ); // 2022-12-12
// java.sql.Date -> LocalDate
new Date( System.currentTimeMillis() ).toLocalDate(); // 2022-12-12
// 특정 날짜의 요일 구하기
LocalDate.of( 2022, 12, 12 ).getDayOfWeek(); // MONDAY
// 특정 날짜로부터 일, 월, 주, 연 차이 나는 날짜 구하기
localDate.minusDays( 5 ); // @param long daysToSubtract
localDate.minusMonths( 5 ); // @param long daysToSubtract
localDate.minusWeeks( 5 ); // @param long daysToSubtract
localDate.minusYears( 5 ); // @param long daysToSubtract
// 특정 날짜로부터 몇 일 이후 날짜 구하기 ( 위와 유사 )
localDate.plusDays( 7 ); // @param long amountToAdd
// 특정 날짜가 해당하는 주의 특정 요일 일자 구하기
localDate.with( DayOfWeek.FRIDAY); // 2022-12-16 ( @param DayOfWeek )
// 특정 날짜에서 특정 부분만 바꾸기
LocalDate localDate = LocalDate.now(); // 2022-12-12
localDate.withDayOfMonth( 31 ); // 2022-12-31 ( @param int dayOfMonth )
localDate.withMonth( 1 ); // 2022-01-12 ( @param int month )
localDate.withYear( 2023 ); // 2023-12-12 ( @param int year )
// 윤년 여부
localDate.isLeapYear(); // false
// 해당 월의 첫째 날 구하기
localDate.withDayOfMonth( 1 );
// 해당 월의 마지막 날 구하기
localDate.withDayOfMonth( localDate.lengthOfMonth() );
// 두 날짜 사이의 간격 구하기
LocalDate start = LocalDate.of( 2021, 10, 1 );
LocalDate end = LocalDate.of( 2022, 12, 31 );
Period diff = Period.between( start, end );
diff.getYears(); // 1
diff.getMonths(); // 2
diff.getDays(); // 30
// ChronoUnit 을 이용한 두 날짜 사이 간격 구하기
long diffMonth = ChronoUnit.MONTHS.between( start, end ); // 14
long diffWeek = ChronoUnit.WEEKS.between( start, end ); // 65
long diffDay = ChronoUnit.DAYS.between( start, end ); // 456
[Java8 Time API] Duration과 Period 사용법 (+ChronoUnit)