1. 서론
이번 포스팅에서는 Chapter12의 새로운 날짜와 시간 API에 대해 진행하도록 하겠습니다.
2. LocalDate, LocalTime, Instant, Duration, Period 클래스
java.time 패키지에는 LocalDate, LocalTime, LocalDateTime, Instant, Duration, Period 등의 새로운 클래스를 제공합니다.
1) LocalDate 와 LocalTime 사용
LocalDate 인스턴스는 시간을 제외한 날짜를 표현하는 불변 객체입니다.
LocalDate는 팩토리 메서드 of를 통해 생성이 가능합니다.
아래는 2017년 9월 21일의 LocalDate를 만들어 사용하는 예제입니다.
LocalDate date = LocalDate.of(2017, 9, 21);
int year = date.getYear(); // 2017
Month month = date.getMonth(); // 9월
int day = date.getDayOfMonth(); // 21
DayOfWeek dow = date.getDayOfWeek(); // 목요일
int len = date.lengthOfMonth(); // 31 (월의 일 수)
boolean deal = date.isLeapYear(); // false (윤년 유무)
현재 날짜를 구할때는 팩토리 메서드 now를 사용하면 됩니다.
아래는 예제입니다.
LocalDate today = LocalDate.now();
아래는 LocalDate 객체에서 값을 얻는 또 다른 방법입니다.
int year = date.get(ChronoField.YEAR);
int month = date.get(ChronoField.MONTH_OF_YEAR);
int day = date.get(ChronoField.DAY_OF_MONTH);
LocalTime은 날짜가 아닌 시간을 제공하는 클래스입니다.
LocalTime 역시 of 메서드를 통해 생성이 가능하며, (시, 분), (시, 분, 초) 각각 인수로 받아 생성 가능하도록 오버로드 되어 있습니다.
아래는 13시 24분 50초 를 만드는 예제 입니다.
LocalTime time = LocalTime.of(13, 45, 20);
int hour = time.getHour();
int minute = time.getMinute();
int second = time.getSecond();
날짜 혹은 시간의 정보를 담고있는 문자열에서 LocalDate, LocalTime으로 만들고 싶은 경우가 있습니다.
이를 위해, LocalDate, LocalTime 은 parse 메서드를 제공합니다.
아래는 예제 입니다.
LocalDate date = LocalDate.parse("2017-09-21");
LocalTime time = LocalTime.parse("13:45:20");
2) 날짜와 시간 조합
LocalDateTime은 날짜와 시간 정보를 모두 가지고 있는 클래스입니다.
아래는 LocalDateTime 을 만드는 예제입니다.
LocalDateTime dt1 = LocalDateTime.of(2017, Month.SEPTEMBER, 21, 13, 45, 20);
LocalDateTime dt2 = LocalDateTime.of(date, time);
LocalDateTime dt3 = date.atTime(13 ,45 ,20);
LocalDateTime dt4 = date.atTime(time);
LocalDateTime dt5 = time.atDate(date);
반대로 LocalDateTime 에서 LocalDate, LocalTime 만을 빼내고 싶은 경우에는 아래와 같이 toLocalDate, toLocalTime 메서드를 사용하면 됩니다.
LocalDate date1 = dt1.toLocalDate();
LocalTime time1 = dt1.toLocalTime();
3) Instant 클래스 : 기계의 날짜와 시간
Instant 클래스는 유닉스 에포크 시간을 기준으로 특정 지점까지의 시간을 초로 표현합니다.
또한, 이 클래스는 나노초의 정밀도를 제공합니다.
아래는 Instant 인스턴스를 만드는 예제입니다.
Instant.ofEpochSecond(3);
Instant.ofEpochSecond(3, 0);
Instant.ofEpochSecond(2, 1000000000);
Instant.ofEpochSecond(4, -1000000000);
Instant 클래스 역시 정적 메서드로 now를 제공합니다.
Instant는 초, 나노초 정보를 가지고 있기 때문에 LocalDate, LocalTime와 같이 사람이 읽을 수 있는 정보를 제공하지 않습니다.
대신 Period와 Duration와는 함께 활용할 수 있습니다.
4) Duration 과 Period 정의
Duration은 두 시간 차의 정보를 가지고 있는 클래스입니다.
아래는 Duration을 생성하는 예제입니다. 생성시에는 LocalTime, LocalDateTime, Instant를 활용할 수 있습니다.
Duration d1 = Duration.between(time1, time2);
Duration d2 = Duration.between(dateTime1, dateTime2);
Duration d3 = Duration.between(instant1, instant2);
Period는 시간이 아닌 두 날짜 차의 정보를 가지고 있는 클래스입니다.
아래는 Period를 생성하는 예제입니다.
Period tenDays = Period.between(LocalDate.of(2017, 9, 11), LocalDate.of(2017, 9, 21));
Duration과 Period는 자체적으로도 생성이 가능하도록 팩토리 메서드들을 제공합니다.
아래는 예제입니다.
Period tenDays = Period.ofDays(10);
Period threeWeeks = Period.ofWeeks(3);
Period twoYearsSixMonthsOneDay = Period.of(2, 6, 1);
지금까지 알아본 클래스들은 모두 불변 객체로 생성하여 제공합니다.
3. 날짜 조정, 파싱, 포매팅
기존 날짜, 시간 데이터를 절대적으로 변경하고 싶은 경우가 있습니다.
이런 경우 with 관련 메서드를 통해 가능합니다.
with 메서드를 사용한다고 기존 객체의 값이 변하는것이 아니며, 새로운 객체에 값만을 바꿔 제공합니다.
이는 불변 객체라는 특징을 제공하기 위해서 입니다.
아래는 예제입니다.
LocalDate date1 = LocalDate.of(2017, 9 , 21);
LocalDate date2 = date1.withYear(2011); // 2011-09-21
LocalDate date3 = date2.withDayOfMonth(25); // 2011-09-25
LocalDate date4 = date3.with(ChronoField.MONTH_OF_YEAR, 2); // 2011-02-25
상대적인 방법으로도 변경도 가능합니다.
아래는 예제입니다.
LocalDate date1 = LocalDate.of(2017, 9, 21);
LocalDate date2 = date1.plusWeeks(1);
LocalDate date3 = date2.minusYears(6);
LocalDate date4 = date3.plus(6, ChronoUnit.MONTHS);
1) TemporalAdjusters 사용하기
복잡한 날짜 조정기능이 필요한 경우 with 메서드에 TemporalAdjusters 를 사용하여 해결할 수 있습니다.
아래는 TemporalAdjusters를 사용하는 한 예제입니다.
LocalDate date1 = LocalDate.of(2014, 3, 18); // 2014-03-18
LocalDate date2 = date1.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)); // 2014-03-23
LocalDate date3 = date2.with(TemporalAdjusters.lastDayOfMonth()); // 2014-03-31
TemporalAdjusters 에서 제공하는 메서드가 없는 경우에는 TemporalAdjuster 함수형 인터페이스를 구현하여 사용하면 됩니다.
아래는 TemporalAdjuster 입니다.
@FunctionalInterface
public interface TemporalAdjuster {
Temporal adjustInto(Temporal temporal);
}
2) 날짜와 시간 객체 출력과 파싱
날짜와 시간 관련에서는 포매팅과 파싱은 서로 떨어질 수 없는 관계입니다.
때문에, java에서는 DateTimeFormatter를 제공하여 손쉽게 날짜나 시간을 특정 형식의 문자열로 만들어 줍니다.
아래는 예제입니다.
LocalDate date = LocalDate.of(2014, 3, 18);
String s1 = date.format(DateTimeFormatter.BASIC_ISO_DATE);
String s2 = date.format(DateTimeFormatter.ISO_LOCAL_DATE);
반대로 문자열에서 날짜나 시간으로도 변환시 사용할 수도 있습니다.
아래는 예제입니다.
LocalDate date1 = LocalDate.parse("20140318", DateTimeFormatter.BASIC_ISO_DATE);
LocalDate date2 = LocalDate.parse("2014-03-18", DateTimeFormatter.ISO_LOCAL_DATE);
DateTimeFormatter 은 기존의 java.util.DateFormat과 달리 쓰레드에 안전합니다.
추가로 DateTimeFormatter 은 특정 패턴으로도 포매팅을 제공합니다.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
LocalDate date1 = LocalDate.of(2014, 3, 18);
String formattedDate = date1.format(formatter);
LocalDate date2 = LocalDate.parse(formattedDate, formatter);
좀 더 복합적인 포매팅을 원할시에는 DateTimeFormatterBuilder 를 사용하면 됩니다.
4. 마무리
이번 포스팅에서는 Chapter12 새로운 날짜와 시간 API에 대해 진행하였습니다.
다음에는 Chapter13 디폴트 메서드에 대해 포스팅하겠습니다.
'Programming > ModernJavaInAction' 카테고리의 다른 글
(14) 자바 모듈 시스템 (0) | 2020.05.23 |
---|---|
(13) 디폴트 메서드 (0) | 2020.05.23 |
(11) null 대신 Optional 클래스 (0) | 2020.05.02 |
(10) 람다를 이용한 도메인 전용 언어 (0) | 2020.04.19 |
(9) 리팩터링, 테스팅, 디버깅 (0) | 2020.04.13 |