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

Bas*_*que 12 java period java-time

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

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

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

Joda-TimePeriod课程处理整个时期.为什么不在java.time?还有其他一些机制吗?

Jod*_*hen 14

在Java SE 8中,应用程序负责创建类链接Period,Duration如果需要的话.

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

请记住,"客户占用酒店房间2天17个半小时,P2DT17H30M"有可能因DST切换而变得复杂.使用PeriodDuration单独的东西是明确的 - Period受DST切换影响而Duration不是.

在设计方面,原始java.time Period确实包括小时,分钟和秒.然而,这导致需要许多方法和复杂的Javadoc来描述规范化和DST周围的所有可能性.通过分离概念,每个概念与时间线的相互作用更加清晰.请注意,这两个类还与SQL设计("年度到月份"和"从第天到第二天"的概念)有关.

目前没有计划在这个领域为Java SE 9添加新类,但是不能完全排除它,因为XML/ISO-8601允许单个组合表示.


Men*_*ild 5

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字符串.它是为相对时间而设计的.


Bas*_*que 5

org.threeten.extra.PeriodDuration

ThreeTen-EXTRA项目提供一类组合PeriodDuration。简单地叫PeriodDuration

ISO-8601日历系统中的时间量,其中包含时间段和持续时间。

此类根据时间段和持续时间对数量或时间量进行建模。期间是基于日期的时间量,包括年,月和日。持续时间是基于时间的时间量,由秒和纳秒组成。有关更多详细信息,请参见Period和Duration类。

时段中的日期考虑了夏令时更改(23或25小时制)。执行计算时,首先添加期间,然后添加持续时间。

警告:请务必阅读JodaStephen的答案,以了解尝试合并Period和所涉及的问题Duration。在实践中这样做很少有意义,尽管这与我们的直觉相反。