tl;dr
Use the org.threeten.extra.PeriodDuration
class.
PeriodDuration
.between(
LocalDate
.of( 2023 , Month.JANUARY , 23 )
.atTime( LocalTime.NOON )
.atZone( ZoneId.of( "America/New_York" ) ) ,
LocalDate
.of( 2023 , Month.JANUARY , 23 )
.atTime( LocalTime.NOON )
.atZone( ZoneId.of( "America/New_York" ) )
.plusDays( 2 )
.plusHours( 17 )
.plusMinutes( 30 )
)
.normalizedStandardDays()
.toString()
P2DT17H30M
Details
The Answer by MC Emperor is correct and wise. Always think twice before making use of a time span combining years-months-days with hours-minutes-seconds.
PeriodDuration
But if you insist on that combination, there is a class for that. You will find it in the ThreeTen-Extra library. This library is led by the same man, Stephen Colebourne, who leads the java.time (JSR 310) framework and its predecessor, Joda-Time.
The org.threeten.extra.PeriodDuration
class represents an amount of time in the ISO 8601 calendar system that combines a period and a duration.
Here is some example code.
ZoneId z = ZoneId.of( "America/New_York" );
LocalDate ld = LocalDate.of( 2023 , Month.JANUARY , 23 );
LocalTime lt = LocalTime.NOON;
ZonedDateTime start = ZonedDateTime.of( ld , lt , z );
ZonedDateTime end = start.plusDays( 2 ).plusHours( 17 ).plusMinutes( 30 );
PeriodDuration pd = PeriodDuration.between( start , end );
Dump to console.
System.out.println( start + "/" + end + " = " + pd );
When run:
2023-01-23T12:00-05:00[America/New_York]/2023-01-26T05:30-05:00[America/New_York] = P3DT-6H-30M
Notice in that result we have negative amounts for hours and minutes. This is because the two-phase logic:
- First, examine dates,
LocalDate
objects. Use Period.between
to count days where the beginning is inclusive while the ending is exclusive. From the 23rd to the 26th is 3 days.
- Second, examine time-of-day values,
LocalTime
objects. Use Duration.between
to calculate elapsed time. We are calculating a duration between noon and 5:30 AM, so we must go back in time six and a half hours.
Therefore our result is 3 days minus 6.5 hours.
You can see this logic in the open source code.
If you want to smooth out this result to flip the negative hours-minutes, add call to PeriodDuration#normalizedStandardDays()
.
PeriodDuration pd = PeriodDuration.between( start , end ).normalizedStandardDays();
2023-01-23T12:00-05:00[America/New_York]/2023-01-26T05:30-05:00[America/New_York] = P2DT17H30M
P2DT17H30M = P3DT-6H-30M
We now get 2 days and 17.5 hours, P2DT17H30M. This is the same amount of time as 3 days minus 6.5 hours, P3DT-6H-30M.