Does the java.time
library provide a consolidated way to parse the entire ISO-8601 Duration Specification?
The Alexa Slot Type reference for duration lists some example strings to expect when using the AMAZON.DURATION slot type. All strings are in ISO-8601 Duration, but P2YT3H10
cannot be parsed by either java.time.Period
or java.time.Duration
.
Seq(
"PT10M",
"PT5H",
"P3D",
"PT45S",
"P8W",
"P7Y",
"PT5H10M",
"P2YT3H10"
).map { s =>
s -> Try {
try {
Period.parse(s)
} catch {
case ex: Throwable => Duration.parse(s)
}
}.map(x => x.toString -> x.getClass.getSimpleName)
}
.foreach(println)
Results:
(PT10M,Success((PT10M,Duration)))
(PT5H,Success((PT5H,Duration)))
(P3D,Success((P3D,Period)))
(PT45S,Success((PT45S,Duration)))
(P8W,Success((P56D,Period)))
(P7Y,Success((P7Y,Period)))
(PT5H10M,Success((PT5H10M,Duration)))
(P2YT3H10,Failure(java.time.format.DateTimeParseException: Text cannot be parsed to a Duration))
Briefly, the ISO 8601 notation consists of a P character, followed by years, months, weeks, and days, followed by a T character, followed by hours, minutes, and seconds with a decimal part, each with a single-letter suffix that indicates the unit. Any zero components may be omitted.
Job Duration Regular Employment. If you're looking for something a little more permanent, this is your schedule. These year-round opportunities can be full-time, reduced-time, or part-time.
Hugos answer is only related to one detail aspect of the ISO-8601-standard, namely the combination of date and time part with a "T"-separator. This detail is indeed not supported by java.time
but supported by the external library Threeten-Extra (using the class PeriodDuration
in the version v1.2). However:
One variation is the usage of weeks in the form "P8W". Both java.time
and Threeten-Extra automatically change it to "P56D" but don't leave it in week-related form when parsing and formatting. A similar view can be obtained when looking at the time components. java.time.Duration
cannot directly store hours or minutes but automatically convert it to seconds. When formatting an automatical normalization is performed, too. Example:
System.out.println(Duration.parse("PT4200S")); // PT1H10M
So in both cases: What you put inside during construction is not always what you get when formatting.
Other points:
java.time
uses two different terms, namely Period
and Duration
(either date-related or time-related).java.time
allows signs even inside the representations and interprete signs as component-related. Note that XML-Schema only handles signs preceding the whole duration expression (before "P"), that is not component-related but duration-related.java.time.Duration
only supports the dot.Finally we can state:
The ISO-8601-standard is only partially supported by java.time
(and Threeten-Extra which only supports the combination of the classes Period
and java.time.Duration
as additional detail).
Alternative solution for true ISO-8601-support:
If you want or even need to overcome the limitations baked into java.time
then you can use my library Time4J which supports all the additional details of ISO-8601. See the API of class net.time4j.Duration. Following examples also show the compatibility with java.time
:
Duration<CalendarUnit> d1 = Duration.parseCalendarPeriod("P8W");
System.out.println(d1); // P8W
System.out.println(d1.getPartialAmount(CalendarUnit.WEEKS)); // 8
System.out.println(Duration.Formatter.ofPattern(CalendarUnit.class, "W' weeks'").format(d1)); // 8 weeks
System.out.println(PrettyTime.of(Locale.GERMAN).print(d1)); // 8 Wochen
LocalDate ld = LocalDate.of(2017, 9, 17);
System.out.println(PlainDate.from(ld).plus(d1)); // 2017-11-12
System.out.println(PlainDate.of(2017, 9, 17).plus(d1)); // 2017-11-12
Duration<IsoUnit> d2 = Duration.parsePeriod("P2DT5H10M");
LocalDateTime ldt = LocalDateTime.of(2017, 9, 17, 19, 15);
System.out.println(PlainTimestamp.from(ldt).plus(d2)); // 2017-09-20T00:25
System.out.println(PlainTimestamp.of(2017, 9, 17, 19, 15).plus(d2)); // 2017-09-20T00:25
System.out.println(PrettyTime.of(Locale.GERMAN).print(d2)); // 2 Tage, 5 Stunden und 10 Minuten
Duration<IsoUnit> d3 = Duration.parsePeriod("P0001-01-02T05:10:04");
System.out.println(d3); // P1Y1M2DT5H10M4S
LocalDateTime ldt = LocalDateTime.of(2017, 9, 17, 19, 15);
System.out.println(PlainTimestamp.from(ldt).plus(d3)); // 2018-10-20T00:25:04
Side note: Formatting of durations is possible in actually 86 languages.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With