Java - 解析日期/期间的优雅方式?

标签 java datetime java-8 duration period

根据 ISO-8601 标准,有 4 种表达间隔/持续时间的方式:

  1. 开始和结束,例如“2007-03-01T13:00:00Z/2008-05-11T15:30:00Z”

  2. 开始和持续时间,例如“2007-03-01T13:00:00Z/P1Y2M10DT2H30M”

  3. 持续时间和结束时间,例如“P1Y2M10DT2H30M/2008-05-11T15:30:00Z”

  4. 只有持续时间,例如“P1Y2M10DT2H30M”,带有额外的上下文信息

仅使用 Java 8(没有 Joda、扩展等),是否有任何优雅的方式来处理案例 1-3?

我知道 Duration.Parse()Period.Parse(),但我想知道是否有一种优雅的方式来处理这 4 种情况。例如:

String datePeriod = "2016-07-21/P6D";
String twoDates   = "2016-07-21/2016-07-25";

Duration d = Duration.parse(datePeriod); // DateTimeParseException
Duration p = Duration.parse(twoDates); // same

我目前的思考过程非常草率,我 100% 确定有更好的方法。比如用嵌套的 try/catch block 分别处理 4 个案例,这看起来有点像反模式。 (在 / 上拆分,解析第一个 block 的日期,检查错误,解析第一个 block 的句点,解析第二个 block 的日期,检查错误......你明白了)

如有任何提示,我们将不胜感激!

--

此外,答案在 ISO 8601 Time Interval Parsing in Java不要以任何方式真正帮助我,因为最佳答案只关心 PT... 的东西。

最佳答案

拆分这些东西并没有真正的反模式。 Oracle 已将这些单独的解析器的职责分开,如果我们想在这种编排中一起使用它们,则由我们来确保我们以合理的方式再次将各个部分剥离在一起。

也就是说,我有一个与核心 Java 8 一起工作的解决方案,并利用了 Function 和一些自定义类。为简洁起见,我将省略自定义 bean,因为它们相当基本,而且主要提升是在 Function 中完成的。

请注意,为了让“Z”被识别为有效条目,您必须使用 DateTimeFormatter.ISO_DATE_TIME 进行解析。此外,为确保正确选择持续时间,请将 "PT" 添加到适合持续时间的文本中。从现有字符串中获取此类详细信息的一种更智能的方法是我留给读者的练习。

Function<String, Range> convertToRange = (dateString) -> {

    String[] dateStringParts = dateString.split("/");
    return new Range(LocalDateTime.parse(dateStringParts[0], DateTimeFormatter.ISO_DATE_TIME),
            LocalDateTime.parse(dateStringParts[1], DateTimeFormatter.ISO_DATE_TIME));
};

Function<String, DurationAndDateTime> convertToDurationAndDateTime = (dateString) -> {
    String[] dateStringParts = dateString.split("/");
    String[] durationAndPeriodParts = dateStringParts[1].split("T");
    return new DurationAndDateTime(Period.parse(durationAndPeriodParts[0]),
            Duration.parse("PT" + durationAndPeriodParts[1]),
            LocalDateTime.parse(dateStringParts[0], DateTimeFormatter.ISO_DATE_TIME));
};


Function<String, DurationAndDateTime> convertToDateTimeAndDuration = (dateString) -> {
    String[] dateStringParts = dateString.split("/");
    String[] durationAndPeriodParts = dateStringParts[0].split("T");
    return new DurationAndDateTime(Period.parse(durationAndPeriodParts[0]),
            Duration.parse("PT" + durationAndPeriodParts[1]),
            LocalDateTime.parse(dateStringParts[1], DateTimeFormatter.ISO_DATE_TIME));
};

Function<String, DurationOnly> convertToDurationOnlyRelativeToCurrentTime = (dateString) -> {
    String[] durationAndPeriodParts = dateString.split("T");
    return new DurationOnly(Period.parse(durationAndPeriodParts[0]),
            Duration.parse("PT" + durationAndPeriodParts[1]));
};

关于Java - 解析日期/期间的优雅方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44622083/

相关文章:

java - 沿着标记移动相机

java - 如果日期不包含时区,则从 FormDataBodyPart/Jackson 输入 json 时抛出异常

sql-server-2005 - 如何在 T-SQL 中将 DateTime 转换为精度大于天的数字?

javascript - 如何将 mysql 日期转换为 var obj [新日期?

java - Java 8 中函数式接口(interface)的定义

java - Gson序列化: how to cast generic class and generic data inside it?

java - 如果 spring 中的 path 属性引用了另一个类的对象,那么它的值是多少

datetime - JPA2 标准和 Java 8 日期和时间 API

java - Java 8 Streams 中的过滤映射

java - 用java制作一个截屏软件