Jod*_*hen 14
在Java SE 8中,应用程序负责创建类链接Period,Duration如果需要的话.
请注意,a Duration包含秒数,而不是单独的秒数,分钟数和小时数.秒数可以超过24小时,因此Duration可以代表"日".但这是一个固定的24小时工作日.相比之下,"日期"的表示Period是描述性的并且考虑了DST."a"的状态Period由三个单独的字段组成 - 日,月和年.
请记住,"客户占用酒店房间2天17个半小时,P2DT17H30M"有可能因DST切换而变得复杂.使用Period和Duration单独的东西是明确的 - Period受DST切换影响而Duration不是.
在设计方面,原始java.time Period确实包括小时,分钟和秒.然而,这导致需要许多方法和复杂的Javadoc来描述规范化和DST周围的所有可能性.通过分离概念,每个概念与时间线的相互作用更加清晰.请注意,这两个类还与SQL设计("年度到月份"和"从第天到第二天"的概念)有关.
目前没有计划在这个领域为Java SE 9添加新类,但是不能完全排除它,因为XML/ISO-8601允许单个组合表示.
与java.time(JSR-310)相关的简短回答:
不,该套餐不提供解决方案.
或者,您可以使用包中的类Durationjavax.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
Run Code Online (Sandbox Code Playgroud)
如果您要求限制/问题,那么您将获得一个列表:
某些(替代)ISO格式P0001-04-20T4H无法解析.
定义的某些方法javax.xml.datatype.Duration依赖于内部Calendar实例(已记录),以便在Duration保存非常大的值的实例时这些方法可能不起作用.
如果在Calendar-instance 上运行,使用小数秒可能会很尴尬,有时精度也会受到限制.
使用Calendar-instance 只有一种单一的规范化方法.至少这种方法以标准方式考虑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和用于实际78种语言的本地化打印的net.time4j.PrettyTime).该类Duration提供了解析ISO字符串的静态方法parsePeriod(String)以及各种规范化方法.与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
Run Code Online (Sandbox Code Playgroud)
为了完整性我还应该提到ocpsoft.PrettyTime,但我不确定该库是否能够处理ISO字符串.它是为相对时间而设计的.
org.threeten.extra.PeriodDuration该ThreeTen-EXTRA项目提供一类组合Period和Duration。简单地叫PeriodDuration。
ISO-8601日历系统中的时间量,其中包含时间段和持续时间。
此类根据时间段和持续时间对数量或时间量进行建模。期间是基于日期的时间量,包括年,月和日。持续时间是基于时间的时间量,由秒和纳秒组成。有关更多详细信息,请参见Period和Duration类。
时段中的日期考虑了夏令时更改(23或25小时制)。执行计算时,首先添加期间,然后添加持续时间。
警告:请务必阅读JodaStephen的答案,以了解尝试合并Period和所涉及的问题Duration。在实践中这样做很少有意义,尽管这与我们的直觉相反。