Logo

[Java8 Time API] Duration과 Period 사용법 (+ChronoUnit)

자바8에 추가된 Time 패키지에는 DurationPeriod라는 상당히 비슷해 보이는 2개의 클래스가 있습니다. 이 두개의 클래스는 둘 다 시간의 길이을 나타내기 위해서 사용되는데요. Duration은 두 “시간” 사이의 간격을 나타내는 반면에 Period는 두 “날짜” 사이의 간격을 나타낸다는 차이점이 있습니다. 이 게 무슨 말인지 예제를 통해서 살펴보도록 하겠습니다.

Duration

먼저 Duration 클래스는 두 시간 사이의 간격을 초나 나노 초 단위로 나타냅니다. 다음 예제는 10시 35분 40초10시 36분 50.0000008초 사이의 Duration을 생성 후, 초와 나노 초를 출력하고 있습니다. Duration 클래스의 between() 정적 메서드에 시작 시간과 종료 시간을 넘기면 두 시간의 간격을 나타내는 Duration 객체를 생성해줍니다.

LocalTime start = LocalTime.of(10, 35, 40);
LocalTime end = LocalTime.of(10, 36, 50, 800);

Duration duration = Duration.between(start, end);

System.out.println("Seconds: " + duration.getSeconds());
System.out.println("Nano Seconds: " + duration.getNano());
Seconds: 70
Nano Seconds: 800

시작 시간과 종료 시간 없이 Duration 클래스의 ofXxx() 정적 메서드를 사용하면 다음과 같이 바로 Duration 클래스를 생성할 수 있습니다. Duration 클래스를 통해 제어할 수 있는 가장 큰 시간 단위는 “일” 입니다. 그보다 큰 시간 단위는 Period 클래스를 통해서 제어가 가능하며 다음 섹션에서 자세히 다루도록 하겠습니다.

Duration ofMinutes = Duration.ofMinutes(1);
System.out.printf("1 minute is %d seconds\n", ofMinutes.getSeconds());

Duration ofHours = Duration.ofHours(1);
System.out.printf("1 hour is %d seconds\n", ofHours.getSeconds());

Duration ofDays = Duration.ofDays(1);
System.out.printf("1 day is %d seconds\n", ofDays.getSeconds());
1 minute is 60 seconds
1 hour is 3600 seconds
1 day is 86400 seconds

DurationPnDTnHnMn.nS 포맷을 사용하고 있으며, parse() 정적 메소드를 사용해서 이 포맷을 따르는 문자열로 부터 객체를 생성할 수 있습니다.

Duration duration = Duration.parse("PT10H36M50.008S");
System.out.println(duration);
System.out.printf("Seconds: %d, Nano Secodns: %d\n", duration.getSeconds(), duration.getNano());
PT10H36M50.008S
Seconds: 38210, Nano Secodns: 8000000

Period

한편, Period 클래스는 두 날짜 사이의 간격을 년/월/일 단위로 나타냅니다. Duration과 마찬가지로 between() 정적 메소드를 제공하고 있으며, 시작 날짜와 종료 날짜를 나타내는 두 개의 LocalDate 객체를 인자로 받습니다. 아래 예제는 세계 2차 대전이 얼마동안 지속이 되었는지를 구하는 코드입니다. 1939년 9월 1일에 시작되어 1945년 9월 2일에 끝난 이 전쟁은 6년 1일간 치뤄졌습니다.

LocalDate startDate = LocalDate.of(1939, 9, 1);
LocalDate endDate = LocalDate.of(1945, 9, 2);

Period period = Period.between(startDate, endDate);

System.out.println("Years: " + period.getYears());
System.out.println("Months: " + period.getMonths());
System.out.println("Days: " + period.getDays());
Years: 6
Months: 0
Days: 1

시작 날짜와 종료 날짜 없이 of() 메서드를 통해서 바로 Period 객체를 생성할 수도 있습니다.

Period period = Period.of(6, 0, 1);

System.out.println("Years: " + period.getYears());
System.out.println("Months: " + period.getMonths());
System.out.println("Days: " + period.getDays());
Years: 6
Months: 0
Days: 1

PeroidPnYnMnD 포맷을 사용하고 있으며, parse() 정적 메소드를 사용해서 이 포맷을 따르는 문자열로 부터 객체를 생성할 수 있습니다.

Period period = Period.parse("P6Y1D");
System.out.println(period);
System.out.println("Years: " + period.getYears());
System.out.println("Months: " + period.getMonths());
System.out.println("Days: " + period.getDays());
P6Y1D
Years: 6
Months: 0
Days: 1

ChronoUnit

Duration 또는 Period 객체를 생성하지 않고도 간편하게 특정 시간 단위로 시간의 길이를 구하는 방법이 있습니다. 바로 아래 예체처럼 ChronoUnit을 사용하면 됩니다.

LocalDate startDate = LocalDate.of(1939, 9, 1);
LocalDate endDate = LocalDate.of(1945, 9, 2);

long months = ChronoUnit.MONTHS.between(startDate, endDate);
long weeks = ChronoUnit.WEEKS.between(startDate, endDate);
long days = ChronoUnit.DAYS.between(startDate, endDate);

System.out.println("Months: " + months);
System.out.println("Weeks: " + weeks);
System.out.println("Days: " + days);

LocalTime startTime = LocalTime.of(10, 35, 40);
LocalTime endTime = LocalTime.of(10, 36, 50, 800);

long hours = ChronoUnit.HOURS.between(startTime, endTime);
long minutes = ChronoUnit.MINUTES.between(startTime, endTime);
long seconds = ChronoUnit.SECONDS.between(startTime, endTime);

System.out.println("Hours: " + hours);
System.out.println("Minutes: " + minutes);
System.out.println("Seconds: " + seconds);
Months: 72
Weeks: 313
Days: 2193
Hours: 0
Minutes: 1
Seconds: 70

이상으로 Java8에서 시간의 길이를 다루는 다양한 방법에 대해서 알아보았습니다.

참고