본문 바로가기
JAVA

[JAVA] Duration CLASS

by w1z 2024. 4. 18.

1. Period와 Duration 클래스

Period는 날짜간의 차이를 나타내고, Duration은 시간간의 차이를 계산하는 클래스입니다.

날짜 - 날짜 = Period
시간 - 시간 = Duration

 

between() 메서드

두 날짜 date1과 date2의 차이를 나타내는 Period는 between()으로 얻을 수 있습니다.

LocalDate date1 = LocalDate.of(2014, 1, 1);
LocalDate date2 = LocalDate.of(2015, 12, 31);
		
Period pe = Period.between(date1, date2);

System.out.println("date1=" + date1);
System.out.println("date2=" + date2);
System.out.println("pe=" + pe); // P1Y11M30D : 1년 11월 30일 차이
        
System.out.println("YEAR=" + pe.getYears());   // YEAR= 1
System.out.println("MONTH=" + pe.getMonths()); // MONTH= 11
System.out.println("DAY=" + pe.getDays());     // DAY= 30

다음은 두 시간 time1과 time2간의 차이를 나타내는 Duration은 between()으로 얻을 수 있습니다. 단, Duration 클래스는 getHours(), getMinutes()과 같은 메서드가 없습니다. Duration 클래스의 시간단위는 초(seconds)와 나노초(nanos)밖에 없습니다.

LocalTime time1 = LocalTime.of(0, 0, 0);
LocalTime time2 = LocalTime.of(12, 23, 56); // 12시간 23분 56초
		
Duration du = Duration.between(time1, time2);
		
System.out.println("time1=" + time1);
System.out.println("time2=" + time2);
System.out.println("du=" + du); // PT12H23M56S : 12시간 23분 56초 차이

 

Period와 Duration 클래스의 단위 확인

// Period와 Duration 단위 확인
System.out.println("Period Unit   : " + pe.getUnits()); // [Years, Months, Days]
System.out.println("Duration Unit : " + du.getUnits()); // [Seconds, Nanos]

 

Duration 클래스의 시간 계산

Duration 클래스는 시간 단위가 초(seconds)/나노초(nano) 밖에 없기 때문에 시간을 다음과 같이 계산할 수 있습니다.

// Duration.getSeconds(), Duration.getNano()를 활용한 시/분/초/나노초 계산
long hour = du.getSeconds() / 3600;
long min  = (du.getSeconds() - hour*3600) / 60;
long sec  = (du.getSeconds() - hour*3600 - min*60) % 60;
int nano  = du.getNano();
System.out.printf("%02d:%02d:%02d.000%d\n", hour, min, sec, nano); // 12:23:56.0000

위와 같은 방법을 개선하여 다음과 같이 Duration을 LocalTime으로 변환한 다음에 LocalTime이 가지고 있는 get 메서드들을 사용할 수 있습니다.

LocalTime tmpTime = LocalTime.of(0, 0).plusSeconds(du.getSeconds());
		
System.out.println("HOUR=" + tmpTime.getHour());
System.out.println("MINUTE=" + tmpTime.getMinute());
System.out.println("SECOND=" + tmpTime.getSecond());
System.out.println("NANO=" + tmpTime.getNano());

 

between() 과 until() 메서드

until() 메서드는 between() 메서드와 거의 같은 일을 수행합니다. 단, between() 메서드는 static 메서드이고 until() 메서드는 인스턴스 메서드입니다.

		// until 메서드의 사용
		LocalDate today = LocalDate.of(2022, 06, 20);
		LocalDate birthday = LocalDate.of(2022, 11, 07);
		Period p1 = today.until(birthday);
		System.out.println(p1); // P4M18D, 4달+18일
		
		long dday = today.until(birthday, ChronoUnit.DAYS);
		System.out.println(dday); // 140일

 

of(), with() 메서드

Period, Duration 메서드중 하나인 of() 메서드는 매개변수에 특정 일자나 시간을 넣으면 Period, Duration 인스턴스를 생성하여 반환합니다. with() 메서드는 Period, Duration 인스턴스의 특정 일자나 시간 필드의 값을 변경하는 메서드입니다.

 

Period

  • of(), ofYears(), ofMonths(), ofWeeks(), ofDays()

Duration

  • of(), ofDays(), ofHours(), ofMinutes(), ofSeconds()
	@Order(7)
	@Test
	void PeriodOfMethodTest() {
		printMethodName("PeriodOfMethodTest");
		
		Period p1y12m31d = Period.of(1, 12, 31); // 1년 12개월 31일 차이
		Period p1y = Period.ofYears(1);          // 1년 차이
		Period p1m = Period.ofMonths(1);         // 1달 차이
		Period p7d = Period.ofWeeks(1);          // 일주일 차이
		Period p30d = Period.ofDays(30);         // 30일 차이
		System.out.println(p1y12m31d);           // P1Y12M31D
		System.out.println(p1y);                 // P1Y
		System.out.println(p1m);                 // P1M
		System.out.println(p7d);                 // P7D
		System.out.println(p30d);                // P30D		
	}

 

	@Order(9)
	@Test
	void PeriodWithMethodTest() {
		printMethodName("PeriodWithMethodTest");
		
		Period pe = Period.of(1, 6, 10);
		Period periodWithYear2  = pe.withYears(2);
		Period periodWithMonth1 = pe.withMonths(1);
		Period periodWithDay1   = pe.withDays(1);

		System.out.println(pe);                 // P1Y6M10D
		System.out.println(periodWithYear2);    // P2Y6M10D
		System.out.println(periodWithMonth1);   // P1Y1M10D
		System.out.println(periodWithDay1);     // P1Y6M1D
	}

 

Period, Duration 클래스의 사칙연산, 비교연산, 기타 메서드

Period 또는 Duration 인스턴스에 사칙연산 메서드를 수행하여 특정 시간을 더하거나 빼거나 곱하거나 나눌 수 있습니다. 단, Period 클래스에는 나눗셈을 위한 연산은 없습니다.

	/**
	 *title : Period 클래스 사칙연산 메서드
	 * Period minus(TemporalAmount amountToSuctract) : 특정 날짜단위만큼 차감 
	 * Period minusYears(long yearsToSuctract)       : 특정 년도수만큼 차감
	 * Period minusMonths(long monthsToSubtract)     : 특정 월만큼 차감
	 * Period minusDays(long daysToSubtract)         : 특정 일자만큼 차감
	 * Period multipliedBy(int scaler)               : scaler 수만큼 날짜를 곱함    
	 */
	@Order(11)
	@Test
	void PeriodArithmeticOperationMethodTest() {
		printMethodName("PeriodArithmeticOperationMethodTest");
		
		Period pe = Period.of(1, 6, 10);
		
		pe = pe.minusYears(1).multipliedBy(2); // 1년을 빼고 2배를 곱함
		System.out.println(pe);
	}
	
	/**
	 * title : Duration 클래스 사칙연산 메서드
	 * Duration plus(Duration duration) : Duration 인스턴스만큼 차이를 누적
	 * Duration plus(long amountToAdd, TemporalUnit unit) : 특정 시간단위만큼 누적
	 * Duration plusHours(long hoursToAdd)                : 시간 누적
	 * Duration plusMinutes(long minutsToAdd)             : 분 누적
	 * Duration plusSeconds(long secondsToAdd)            : 초 누적
	 * Duration plusMillis(long millisToAdd)              : 밀리초 누적
	 * Duration plusNanos(long nanosToAdd)                : 나노초 누적
	 * Duration multipliedBy(int scaler)                  : scaler만큼 곱함
	 * Duration divideBy(long divisor)                    : divisor만큼 나눔
	 */
	@Order(12)
	@Test
	void DurationArithmeticOperationMethodTest() {
		printMethodName("PeriodAndDurationIsZeroAndIsNegativeMethodTest");
		
		Duration du = Duration.of(120, ChronoUnit.SECONDS);
		
		du = du.plus(Duration.of(1, ChronoUnit.HOURS));
		du = du.plus(1, ChronoUnit.HOURS);
		du = du.plusHours(1);
		du = du.plusMinutes(1);
		du = du.plusSeconds(1);
		du = du.plusMillis(1);
		du = du.plusNanos(1);
		du = du.multipliedBy(1);
		du = du.dividedBy(1);
		System.out.println(du);
	}

 

Period, Duration 클래스의 다른 단위로 변환 - toTotalMonths(), toDays(), toHours(), toMinutes()

Period 또는 Duration 인스턴스를 다른 단위의 값으로 변환하는데 사용합니다.

	/**
	 * title : Period & Duration 다른 단위로 변환
	 * Period 인스턴스 메서드
	 * long toTotalMonths() : 년월일을 월단위로 변환해서 반환 (일 단위는 무시)
	 * 
	 * Duration 인스턴스 메서드
	 * long toDays()        : 일단위로 변환해서 반환
	 * long toHours()       : 시간 단위로 변환해서 반환
	 * long toMinutes()     : 분 단위로 변환해서 반환
	 * long toMillis()      : 밀리초 단위로 변환해서 반환
	 * long toNanos()       : 나노초 단위로 변환해서 반환
	 */
	@Order(15)
	@Test
	void PeriodAndDurationToMethodTest() {
		printMethodName("PeriodAndDurationToMethodTest");
		
		Period pe = Period.of(1, 6, 30);	// 1년 6개월 30일 차이
		long months = pe.toTotalMonths();
		
		Duration du = Duration.of(1, ChronoUnit.DAYS);
		long days = du.toDays();
		long hours = du.toHours();
		long minutes = du.toMinutes();
		long seconds = du.getSeconds();
		long millis = du.toMillis();
		long nanos = du.toNanos();
		
		System.out.println("months : " + months +"개월");
		System.out.println("days : " + days + "일");
		System.out.println("hours : " + hours + "시간");
		System.out.println("minutes : " + minutes + "분");
		System.out.println("seconds : " + seconds + "초");
		System.out.println("millis : " + millis + "밀리초");
		System.out.println("nanos : " + nanos);		
	}

 

References

source code : https://github.com/yonghwankim-dev/java_study/tree/main/ch10
[도서] Java의 정석, 남궁 성 지음

https://yonghwankim-dev.tistory.com/449