java.time
库是否提供了解析整个ISO-8601 Duration Specification的整合方式?
Alexa Slot Type reference for duration列出了使用AMAZON.DURATION插槽类型时需要的一些示例字符串。所有字符串都在ISO-8601持续时间内,但P2YT3H10
或java.time.Period
无法解析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)
结果:
(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))
答案 0 :(得分:5)
Hugos答案仅与ISO-8601标准的一个细节方面有关,即日期和时间部分与" T" -separator的组合。 java.time
确实不支持此详细信息,但外部库Threeten-Extra(使用版本v1.2中的类PeriodDuration
)支持此详细信息。但是:
一种变体是使用周形式" P8W"。 java.time
和Threeten-Extra都会自动将其更改为" P56D"但在解析和格式化时不要以与周相关的形式保留它。查看时间组件时可以获得类似的视图。 java.time.Duration
无法直接存储小时或分钟,但会自动将其转换为秒。当执行格式化自动规范化时也是如此。例如:
System.out.println(Duration.parse("PT4200S")); // PT1H10M
所以在这两种情况下:在构建期间放入的内容并不总是格式化时的内容。
其他要点:
java.time
使用两个不同的术语,即Period
和Duration
(与日期相关或与时间相关)。 java.time
仅支持点。最后我们可以声明:
java.time.Duration
(和Threeten-Extra仅支持类java.time
和Period
的组合作为附加细节)仅部分支持ISO-8601标准。
真正的ISO-8601支持的替代解决方案:
如果您想要甚至需要克服java.time.Duration
中的限制,那么您可以使用我的库Time4J,它支持ISO-8601的所有其他详细信息。请参阅类net.time4j.Duration的API。以下示例还显示了与java.time
的兼容性:
java.time
附注:实际上有86种语言可以格式化持续时间。
答案 1 :(得分:3)
PS :您的输入缺少最后一个字段的指示符(P2YT3H10
- 2年,3小时和10个什么?)。所以,在下面的代码中,我只是假设它是M
(分钟) - 它在10
之后没有指示符的情况下无法工作。
java.time
API分隔了ISO8601持续时间in 2 classes:
java.time.Period
,可以处理date-based fields (years, months and days) java.time.Duration
,可以处理time-based fields *(实际上,根据javadoc:"这个类用秒和纳秒来模拟一个数量或时间量。它可以可以使用其他基于持续时间的单位访问,例如分钟和小时" )不幸的是,这些课程无法处理基于日期和时间的字段的ISO8601持续时间。
另一种方法是使用ThreeTen Extra项目,该项目包含java.time
API的一些扩展。使用此lib,您可以使用org.threeten.extra.PeriodDuration
class,它可以解析完整的ISO8601持续时间:
PeriodDuration pd = PeriodDuration.parse("P2YT3H10M");
然后,您可以从中获取相应的Period
和Duration
:
System.out.println(pd.getPeriod()); // P2Y
System.out.println(pd.getDuration()); // PT3H10M
另一种方法是拆分String
,并分别解析Period
和Duration
:
// split in 2 parts
String input = "P2YT3H10M";
String[] v = input.split("T");
Period p;
Duration d;
if (v.length == 1) { // has only date-based fields
p = Period.parse(input);
d = Duration.ZERO;
} else {
if ("P".equals(v[0])) { // has only time-based fields
p = Period.ZERO;
} else {
p = Period.parse(v[0]);
}
d = Duration.parse("PT" + v[1]);
}
* Duration
也接受天,由于夏令时,这些时间始终被认为是24小时(Period
,一天doesn't necessarily have 24 hours时间效应)。
答案 2 :(得分:0)
Java 8持续时间仅允许天,小时,分钟和秒:
接受的格式基于ISO-8601持续时间格式PnDTnHnMn.nS
https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html#parse-java.lang.CharSequence-