자바에서는 날짜와 시간을 다루는 다양한 클래스들을 제공한다.
오랜시간 사용되어왔지만 불편하다고 악평이 자자한 Date클래스와 Calendar클래스부터 기존의 것들을 답답하게 여긴 사람들이 만든 Joda-Time 라이브러리, JDK8부터 추가된 java.time등이 존재한다. 하지만 Date클래스와 Calendar클래스는 앞서 말했듯 많은 문제점들 때문에 사용하기 불편하다.
기존 클래스들에는 어떤 문제점이 있고, 여러 라이브러리들과 JDK8에서는 이 문제점들을 어떻게 개선했는지를 알아보고자 한다.
Date와 Calendar클래스
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
Date date = cal.getTime();
System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(date)); // 2022-01-24
cal.add(Calendar.MONTH, 1);
date = cal.getTime();
System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(date)); // 2022-02-24
}
간단하게 오늘과 다음달 날짜를 출력해보았다. date를 출력하기 위해 getTime() 메소드를 사용하거나 위 코드에는 나타나있지 않지만 월의 상수값이 0으로 시작한다거나... 몇가지 혼선을 주는 형식이 많이 존재한다.
문제점
불변 객체가 아니다( not immutable)
Calendar cal = Calendar.getInstance();
cal.set(Calendar.MONTH, 2 - 1);
Date와 Calendar클래스는 set메소드를 통해 값을 바꿀 수 있는데, 이는 누군가 악의적으로 변경할 수 있음을 의미한다.
int 상수 필드의 남용
위의 예제처럼 int가 많이 쓰이는데, 월이나 요일을 지정하는 데에 많은 혼란을 유발한다.
헷갈리는 월 지정
Date와 Calendar클래스에서는 1월이 0으로 표현된다.
calendar.set(1582, 10 , 4);
위처럼 작성하면 10월이 아니라 11월이 출력되는 것이다.
일관성 없는 요일 상수
어떤 메소드에서는 일요일이 0이고, 또 다른 메소드에서는 일요일이 1이다. 사용하다보면 일관성이 없어 많이 헷갈릴 것이다.
Date와 Calendar의 불편한 역할 분담
년/월/일 계산은 Date 클래스만으로는 부족해서 각 클래스를 왔다갔다 하는 문제가 있다. 또한 Calendar객체를 생성하고 Date 객체를 생성하는 프로세스를 거치기 때문에 번거롭고 생성비용이 비싸다.
이외에도 여러가지 문제점이 많다.
개발을 시작하는 입장에서 이 클래스를 먼저 다뤘으면 꽤나 머리아팠겠다 싶다.
java.time 패키지
https://gptjs409.github.io/java/2019/09/14/time-1.html
[Java] java.time패키지(1)
java.time패키지
gptjs409.github.io
해당 클래스의 문제점 때문에 대체하여 나온 것이 JDK8부터 추가된 java.time 패키지이다.
Calendar클래스는 날짜와 시간, 시간대를 하나로 표현하는 것에 반해 java.time패키지는 날짜와 시간을 별도의 클래스로 구분한다.
- LocalDate : 날짜
- LocalTime : 시간
- LocalDateTime : 날짜 & 시간
- ZonedDateTime : 날짜 & 시간 & 시간대(time-zone)
Joda-Time에 많은 영향을 받은 API라 Joda-Time 거의 비슷한 비슷한 모습을 하고 있고, 이보다 더 개선된 점도 있다고 한다!
LocalDate와 LocalTime
java.time패키지의 가장 기본이 되는 클래스이다.
- 날짜 가져오기
// 오늘 날짜, 2022-01-26
LocalDate nowDate = LocalDate.now();
// 2022년 1월 1일, 2022-02-01
LocalDate ofDate = LocalDate.of(2022, 1, 1);
// 바로 지금, 2022-01-26T10:15:23
LocalDateTime nowDateTime = LocalDateTime.now();
// 2022년 2월 1일 10시 32분 32초, 2022-02-01T10:32:32
LocalDateTime ofDateTime = LocalDateTime.of(2022, 2, 1, 10, 32, 32);
.now() : 현재의 날짜와 시간을 LocalDate와 LocalTime으로 각각 변환
.of() : 지정된 날짜와 시간으로 LocalDate와 LocalTime객체를 생성
- 특정 시간 / 날짜 가져오기
오늘 자정(0시 0분 0초) 가져온 후 문자열 변환
// 오늘 날짜의 자정(midnight)
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
// 2022-01-26 00:00:00.000
String date = LocalDate.now().atStartOfDay().format(formatter);
내일 날짜 가져오기
// 2022년 1월 26일 10시 32분 32초, 2022-1-26T10:32:32
LocalDateTime ofDateTime = LocalDateTime.of(2022, 2, 26, 10, 32, 32);
// 2022년 1월 27일 10시 32분 32초, 2022-1-27T10:32:32
LocalDateTime tomorrow = ofDateTime.plusDays(1);
내일 날짜의 마지막 시간 가져오기
// 2022년 1월 27일 23시 59분 59초
// 정확히는~ 23:59:59.999999999
LocalDateTime.now().plusDays(1).with(LocalTime.MAX);
정오(오전 12시)
// 오늘 날짜의 정오(오전 12시)
LocalDateTime.now().with(LocalTime.NOON);
- 날짜 변환하기
날짜 정보를 문자열로 변환하거나 Date와 같은 구 버전의 날짜 클래스를 java 8 클래스로 변환할 수 있다.
Date to LocalDateTime
// java.util.Date to java.time.LocalDateTime
LocalDateTime.ofInstant(new Date().toInstant(), ZoneId.systemDefault());
LocalDate to LocalDateTime
// java.time.LocalDate to java.time.LocalDateTime
// 오늘 날짜, 10시 32분 32초
LocalDate.now().atTime(10, 32, 32);
// 오늘 날짜, 자정(0시)
LocalDate.now().atStartOfDay();
LocalDateTime to String
// java.time.LocalDateTime to java.lang.String
// 2022-01-26 10:28:35.043
LocalDateTime.now()
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"));
LocalDateTime to String
// java.time.LocalDate to java.lang.String
// 2022-01-26
LocalDate.now().format(DateTimeFormatter.ISO_DATE);
String to LocalDateTime
// java.lang.String to java.time.LocalDateTime
// 2022-01-26T10:28:35.043
LocalDateTime.parse("2018-12-11 13:43:21.221",
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"));
String to LocalDate
// java.lang.String to java.time.LocalDate
// 2022-02-01
LocalDate.parse("2018-12-11");
- 요일 다루기
가장 가까운 요일, N 번째 요일 등을 간단한 코드로 가져올 수 있다.
오는 일요일(가장 가까운 다음 일요일)
// 1월 26일 기준, 오는 일요일은 1월 30일
LocalDateTime.now().with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
2022년 11월의 4번째 일요일
// 2022년 11월 기준, 네 번째 일요일은 27일
LocalDate.of(2022, 1, 26).with(TemporalAdjusters.dayOfWeekInMonth(4, DayOfWeek.SUNDAY));
2022년 11월의 첫 번째 일요일
// 2022년 11월 기준, 첫 번째 일요일은 6일
LocalDate.of(2022, 11, 26).with(TemporalAdjusters.firstInMonth(DayOfWeek.SUNDAY));
++ java.time패키지 사용법을 깔끔하게 정리한 글
https://madplay.github.io/post/java8-date-and-time
Java 8 날짜와 시간 계산
자바 8에서 추가된 날짜 관련 클래스(LocalDate, LocalDateTime)로 날짜와 시간을 계산해보자.
madplay.github.io
참고
https://d2.naver.com/helloworld/645609
https://gptjs409.github.io/java/2019/09/14/time-1.html
[Java] java.time패키지(1)
java.time패키지
gptjs409.github.io
'Study > JAVA' 카테고리의 다른 글
[JAVA] 디자인패턴 - 빌더 패턴(Builder pattern) (0) | 2022.01.27 |
---|---|
[Java] 디자인패턴 - 싱글톤 패턴 (singleton pattern) (0) | 2021.12.01 |
[JAVA] String, StringBuffer, StringBuilder 차이 및 장단점 (0) | 2021.11.27 |
[Java] 람다식 (Lambda Expression) (0) | 2021.11.26 |
[Java] Stream API (0) | 2021.11.24 |