Java Date - 날짜와 시간 조회 및 조작
날짜 조회하기
날짜와 시간 조회에는 날짜와 시간 항목 중 어떤 필드로 조회할 것인지 정할 필요가 있다.
날짜와 시간의 필드를 갖고 있는 ChronoField
클래스로 사용한다.
먼저 LocalDateTime 객체타입의 dt 변수로 선언한다.
LocalDateTime dt = LocalDateTime.of(2028, 8, 28, 14, 29, 59);
System.out.println(dt);
2028-08-28T14:29:59
TemporalAccessor.get(TemporalField field)
LocalDateTime
포함한 특정 시점 시간을 제공하는 클래스는TemporalAccessor
인터페이스로 포함되어 구현되어 있다.TemporalAccessor
특정 시점의 시간을 조회하는 기능을 제공get(TemporalField field)
호출 시 어떤 날짜와 시간 필드로 조회할지TemporalField
구현인ChronoField
인수로 전달할 수 있다.
해당 시간대로 ChronoField 각 날짜 필드 별 조회해보도록 한다.
YEAR 연도 조회
System.out.println("YEAR = " + dt.get(ChronoField.YEAR));
YEAR = 2028
LocalDateTime 객체의 get 메소드로 ChronoField 필드로 연도를 조회하였다.
MONTH_OF_YEAR 몇 월인지 조회하기
System.out.println("MONTH_OF_YEAR = " + dt.get(ChronoField.MONTH_OF_YEAR));
MONTH_OF_YEAR = 8
DAY_OF_MONTH 몇 일인지 조회하기
System.out.println("DAY_OF_MONTH = " + dt.get(ChronoField.DAY_OF_MONTH));
DAY_OF_MONTH = 28
HOUR_OF_DAY 몇 시인지 조회하기
System.out.println("HOUR = " + dt.get(ChronoField.HOUR_OF_DAY));
HOUR = 14
MINUTE_OF_HOUR 몇 분인지 조회하기
System.out.println("MINUTE = " + dt.get(ChronoField.MINUTE_OF_HOUR));
MINUTE = 29
SECOND_OF_MINUTE 몇 초인지 조회하기
System.out.println("SECOND = " + dt.get(ChronoField.SECOND_OF_MINUTE));
SECOND = 59
편의 메소드 제공
get(ChronoField ...) 형태로 계속 호출 대신 다른 방법으로 출력 하는 방법도 있다.
System.out.println("편의 메소드 제공");
System.out.println("YEAR = " + dt.getYear());
System.out.println("MONTH_OF_YEAR = " + dt.getMonth());
System.out.println("DAY_OF_MONTH = " + dt.getDayOfMonth());
System.out.println("HOUR = " + dt.getHour());
System.out.println("MINUTE = " + dt.getMinute());
System.out.println("SECOND = " + dt.getSecond());
편의 메소드 제공
YEAR = 2028
MONTH_OF_YEAR = AUGUST
DAY_OF_MONTH = 28
HOUR = 14
MINUTE = 29
SECOND = 59
- get(TemporalField field) 코드가 길어지고 번거로운 것으로 자주 사용하는 조회 필드는 간단한 편의메소드로 제공하고 있다.
- dt.get(ChronoField.DAY_OF_MONTH) -> get.getDayOfMonth()
편의 메소드 없음
자주 사용하지 않는 특정 날짜와 필드에 대한 편의 메소드가 없다. 이 경우 ChronoField 로 직접 찾아 넣어주어야 한다.
System.out.println("편의 메소드 없음");
System.out.println("MINUTE_OF_DAY = " + dt.get(ChronoField.MINUTE_OF_DAY));
System.out.println("SECOND_OF_DAY = " + dt.get(ChronoField.SECOND_OF_DAY));
편의 메소드 없음
MINUTE_OF_DAY = 869
SECOND_OF_DAY = 52199
- 자주 사용하지 않으므로 편의 메소드가 없음
- 편의 메소드를 사용하는 것이 가독성이 좋아서 주로 사용하고 편의 메소드가 없는 경우 ChronoField 필드로 직접 호출하도록 한다.
get 메소드는 TemporalAccessor 인터페이스로부터
날짜 및 시간 조정하기
날짜 및 시간 조작에는 어떤 단위로(Unit) 변경할지 정해야 한다. 이럴 때는 ChronoUnit 구현체로 사용한다.
LocalDateTime dt = LocalDateTime.of(2028, 8, 28, 14, 29, 59);
System.out.println(dt);
2028-08-28T14:29:59
위 변수로 계속 이어서 사용하며 조정해보도록 한다.
ChronoUnit.Years - 연도 늘리기
LocalDateTime plusYear = dt.plus(10, ChronoUnit.YEARS);
System.out.println("Plus 10Years: " + plusYear);
Plus 10 Years: 2038-08-28T14:29:59
편의 메소드 - 연도 늘리기
LocalDateTime plusYear = dt.plusYears(10);
System.out.println("Plus 10Years: " + plusYear);
Plus 10 Years: 2038-08-28T14:29:59
Period - 연도 늘리기
Period period = Period.ofYears(10);
LocalDateTime plusYears = dt.plus(period);
System.out.println("Plus 10Years: " + plusYears);
Plus 10Years: 2038-08-28T14:29:59
ChronoUnit.Months - 연도 늘리기
LocalDateTime plusMonths = dt.plus(10, ChronoUnit.MONTHS);
System.out.println("Plus 10MONTHS: " + plusMonths);
Plus 10MONTHS: 2029-06-28T14:29:59
정리
Temporal plus(long amountToAdd, TemporalUnit unit)
- LocalDateTime 포함한 트겆ㅇ 시점의 시간을 제공하는 클래스는 모두 Temporal 인터페이스로 구현된 것을 볼 수 있다.
- Temporal 특정 시점의 시간을 조작하는 시간을 포함한다.
- plus(long amountToAdd, TemporalUnit unit) 호출마다 더하기 할 숫자와 단위를 전달한다.
- 단위는 ChronoUnit 인수로 전달
- 실제 인스턴스의 값은 불변이므로 변경되지 않으므로 새 객체로 전달한다.
편의 메소드 사용
- 자주 사용하는 메소드는 변경 및 조작에도 편의 메소드를 제공한다.
- dt.plus(10, ChronoUnit.YEARS) -> dt.plusYears(10)
Period 사용한 조작
- Period 또는 Duration 기간(시간의 간격)을 갖고 있다. 이 것을 이용해 날짜와 시간의 기간을 더할 수 있다.
날짜와 시간의 Temporal 장점
- 시간을 조회 및 변경에서 TemporalAccessor.get(), Temporal.plus() 인터페이스로 구현 클래스와 무관하게 일관성 있게 조회 및 변경 기능을 진행하였다.
- LocalDateTime, LocalDate, LocalTime, ZonedDateTime, Instant 구현에 관계 없이 일관성 있는 방법으로 시간을 조회하고 조작한다.
단점
- 시간 필드를 조회할 수 없는 상황도 생긴다.
- LocalTime, LocalDate 와 같이 날짜나 시간이 빠진 부분을 조회하면 예외 처리되어 출력하지 않는다.
LocalDate now = LocalDate.now();
System.out.println(now.get(ChronoField.MINUTE_OF_DAY));
Exception in thread "main" java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: MinuteOfDay
대응 방안
- isSupported 와 같이 필드를 조회할 수 있는지 확인할 수 있는 메소드도 제공한다.
LocalDate now = LocalDate.now();
boolean supported = now.isSupported(ChronoField.MINUTE_OF_DAY);
System.out.println(supported);
false
LocalDate 시 분 초를 다루지 않기에 ChronoField.MINUTE_OF_DAY 조회 시 false 값으로 출력한다.