IIUC java.time should end multiple date libraries and related issues, and offer something good and standardized. So it was kinda shock to me to learn, that java.time.Duration violates iso8601 standard. While it should be possible to parse: P2Y1DT1S
, as that is valid by standard, java.time.Duration
will parse only up to days (so you have to workaround via P731DT1S
and java.time.Period
can't do that at all, since it does not allow temporal part.
Questions:
Why? Is there a valid reason not to have interval parsing according to specification? What am I overlooking?
Or is there some readily available class, which will parse ISO8601?
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
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:
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.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
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.
Well, parsing such a string means it yields an object which supports both concepts to be present at the same time – a sort of PeriodDuration
. But there is none in Java, and its rationale is explained here by JodaStephen:
Note that a
Duration
contains an amount of seconds, not separate amounts of seconds, minutes and hours. The amount of seconds can exceed 24 hours, thus aDuration
can represent a "day". But it is a fixed 24 hours day. By contrast, the representation of a "day inPeriod
is descriptive and takes into account DST. The state of aPeriod
is formed from three separate fields - days, months and years.Bear in mind that "The customer occupied the hotel room for 2 days and seventeen and a half hours, P2DT17H30M" has the possibility to be complicated by DST cutovers . Using
Period
andDuration
separately things are clear -Period
is affected by DST cutovers andDuration
is not.
(Emphasis mine.)
So in short, the two concepts handle DST differently, and combining the two complicates things.
Regarding your second question, this answer here suggests ThreeTen Extra.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.