Period
中的java.time类仅处理面向日期的药水:年,月,日。
时间部分怎么样:小时,分钟,秒?
我们如何解析和生成ISO 8601,PnYnMnDTnHnMnS
中定义的完整句点的字符串表示?例如,一天半:P1DT12H
。学年是九个月,P9M
。每年我都会有两周零三天的假期P17D
。客户占用了酒店房间2天17个半小时,P2DT17H30M
。
答案 0 :(得分:13)
在Java SE 8中,如果需要,应用程序负责创建链接Period
和Duration
的类。
请注意,Duration
包含秒数,而不是单独的秒数,分钟数和小时数。秒数可以超过24小时,因此Duration
可以代表“日”。但这是一个固定的24小时工作日。相比之下,“Period
中的”日期的表示是描述性的并且考虑了DST。Period
的状态由三个单独的字段组成 - 日,月和年。
请记住,“客户占用酒店房间2天,17个半小时,P2DT17H30M”有可能因DST切换而变得复杂。事情很明显,Period
和Duration
很明显 - Period
会受到DST切换的影响,而Duration
则不会。{/ p>
在设计方面,原始java.time Period
确实包括小时,分钟和秒。然而,这导致需要许多方法和复杂的Javadoc来描述规范化和DST周围的所有可能性。通过分离概念,每个概念与时间线的相互作用更加清晰。请注意,这两个类还与SQL设计(“年度到月份”和“天到秒”概念)有关。
目前没有计划在这个领域为Java SE 9添加新类,但是不能完全排除它,因为XML / ISO-8601允许单个组合表示。
答案 1 :(得分:5)
与java.time
(JSR-310)相关的简短回答:
不,该套餐不提供解决方案。
或者,您可以使用包Duration 中的课程javax.xml.datatype
来解析PnYnMnDTnHnMnS
之类的字符串。自Java-5以来,它也可用于较旧的JDK版本。例如:
// parsing
String iso = "P2Y4M30DT17H5M57.123S";
javax.xml.datatype.Duration xmlDuration =
DatatypeFactory.newInstance().newDuration(iso);
int years = xmlDuration.getYears();
int months = xmlDuration.getMonths();
int days = xmlDuration.getDays();
int hours = xmlDuration.getHours();
int minutes = xmlDuration.getMinutes();
int fullSeconds = xmlDuration.getSeconds();
BigDecimal seconds = (BigDecimal) xmlDuration.getField(DatatypeConstants.SECONDS);
// generating ISO-string
String xml = xmlDuration.toString();
System.out.println(xml); // P2Y4M30DT17H5M57.123S
如果您要求限制/问题,那么您可以在此处获得一个列表:
无法解析某些(替代)ISO格式,例如P0001-04-20T4H
。
javax.xml.datatype.Duration
中定义的某些方法依赖于内部Calendar
- 实例(已记录),因此如果Duration
的实例包含非常大的值,则这些方法可能无效。
如果在Calendar
- 实例上操作,使用小数秒可能会很尴尬,有时会导致精度有限。
使用Calendar
- 实例只有一种规范化方法。至少这种方法以标准方式考虑了DST效应。
不提供格式化(甚至不提及本地化打印)。
如果你想克服这些问题,那么你可以考虑使用一个外部库(是的,我不会只考虑Joda-Time,其精度受限于毫秒,其国际化也是有限的)。否则,包javax.xml.datatype
的优点是可以节省将外部库嵌入类路径的工作量。
<强>更新强>
关于与外部图书馆相关的评论中的问题,我知道Joda-Time和我的图书馆Time4J。
第一个( Joda-Time )提供了一个名为ISOPeriodFormat的特殊类。这个类也能够解析其他ISO格式(尽管原始ISO-8601-paper中没有提到PyyyyWwwddThhmmss,但缺少对PYYYY-DDD的支持)。 Joda-Time为期间格式化程序定义了构建器驱动的方法,该方法也可用于打印持续时间(句点)。此外,对本地化打印的支持有限(使用13种语言的Joda-Time版本2.9.3)。最后,课程Period
提供了各种规范化方法(请参阅javadoc)。
第二个( Time4J )提供net.time4j.Duration类和两个格式化工具(Duration.Formatter用于基于模式的打印/解析,net.time4j.PrettyTime用于本地化打印实际上是78种语言)。类Duration
提供了解析静态方法parsePeriod(String)的ISO字符串以及各种规范化方法。与java.time
(JSR-310)互操作性的示例,证明可以将此库视为新java-8-date-time-api的强大扩展:
// input: using java.time-package
LocalDateTime start = LocalDateTime.of(2016, 3, 7, 10, 15, 8);
LocalDateTime stop = LocalDateTime.of(2016, 6, 1, 22, 15);
// define how you measure the duration (zone correction would also be possible)
Duration<?> duration =
TimestampInterval.between(start, stop).getDuration(
CalendarUnit.YEARS,
CalendarUnit.MONTHS,
CalendarUnit.DAYS,
ClockUnit.HOURS,
ClockUnit.MINUTES,
ClockUnit.SECONDS
);
// generate standard ISO-representation
String s = duration.toStringISO();
System.out.println(s); // P2M25DT11H59M52S
// parse ISO-String and prove equality with original
System.out.println(Duration.parsePeriod(s).equals(duration)); // true
// adding duration to <start> yields <stop>
System.out.println(start.plus(duration.toTemporalAmount())); // 2016-06-01T22:15
// format in human time
System.out.println(PrettyTime.of(Locale.US).print(duration));
// output: 2 months, 25 days, 11 hours, 59 minutes, and 52 seconds
为了完整性我还应该提到ocpsoft.PrettyTime,但我不确定该库是否能够处理ISO字符串。它是为相对时间设计的。