如何在java.time中处理完整的句号?

时间:2015-09-03 02:44:09

标签: java period java-time

Period中的java.time类仅处理面向日期的药水:年,月,日。

时间部分怎么样:小时,分钟,秒?

我们如何解析和生成ISO 8601PnYnMnDTnHnMnS中定义的完整句点的字符串表示?例如,一天半:P1DT12H。学年是九个月,P9M。每年我都会有两周零三天的假期P17D。客户占用了酒店房间2天17个半小时,P2DT17H30M

Period中的Joda-Time课程处理完整期间。为什么不在java.time?还有其他一些机制吗?

2 个答案:

答案 0 :(得分:13)

在Java SE 8中,如果需要,应用程序负责创建链接PeriodDuration的类。

请注意,Duration包含秒数,而不是单独的秒数,分钟数和小时数。秒数可以超过24小时,因此Duration可以代表“日”。但这是一个固定的24小时工作日。相比之下,“Period中的”日期的表示是描述性的并且考虑了DST。Period的状态由三个单独的字段组成 - 日,月和年。

请记住,“客户占用酒店房间2天,17个半小时,P2DT17H30M”有可能因DST切换而变得复杂。事情很明显,PeriodDuration很明显 - 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字符串。它是为相对时间设计的。