【问题标题】:How to get datetime with and without an offset?如何获得有和没有偏移的日期时间?
【发布时间】:2020-05-01 09:08:02
【问题描述】:

目前我的方法能够解析和格式化带有偏移量的日期和时间。

当我体验过 JUnit 时,我发现 - 对很多人来说非常明显 - 错误是我只能在它包含偏移量时对其进行解析。

我要么得到 Unable to obtain OffsetDateTime from TemporalAccessor 或者我无法用偏移量解析时间。

这是我目前的代码:

工作输入: "2020-01-12T10:30-06:00"

输入无效: "2020-01-12T10:30"

OffsetDateTime offsetDateTime = OffsetDateTime.parse(date, buildIso8601Formatter());
Instant instant = offsetDateTime.toInstant();

return LocalDateTime.ofInstant(instant, ZoneOffset.UTC);

它适用于带有偏移量的日期时间,但反之则不行。

最后,我希望能够在同一方法中解析带/不带偏移量的日期时间。

【问题讨论】:

  • 您能添加一些示例输入吗?
  • @deHaar 已更新。
  • 示例String 无效,因为它缺少:ss 部分几秒钟。它只有几小时和几分钟。这意味着您必须提供自定义模式才能解析它。你能也展示一下buildIso8601Formatter() 的实现(或使用的模式)吗?
  • 另一种可能性是添加秒数,例如"2020-01-12T10:30:00-06:00",然后简单地执行OffsetDateTime offsetDateTime = OffsetDateTime.parse(date)
  • @deHaar 我能够解析它。我提供了一个不起作用的例子。没有偏移量就无法解析字符串。我在有和没有秒的情况下对其进行了测试,但没有显示出差异。我有点理解为什么,但我无法找到正确的路径来引导我找到解决方案。

标签: java date parsing time timezone


【解决方案1】:

时刻

工作输入:“2020-01-12T10:30-06:00”

输入无效:“2020-01-12T10:30”

这些输入是两种非常不同的动物。第一个代表片刻,第二个不代表。第一个确定时间轴上的特定点,第二个没有。

第二个缺少时区或与 UTC 偏移的关键上下文。所以我们不知道第二个输入是代表日本东京 12 日的 10:30,还是突尼斯突尼斯的 10:30,或者美国俄亥俄州托莱多的 10:30——所有的时刻都非常不同,相隔几个小时。

数据源错误

如果您有一个任意省略偏移/区域信息的输入源,那么您自己的 Java 编程没有问题,您的数据源有问题。

想象一个提供一系列货币金额的数据源,其中一些金额表示加元、欧元或日元的货币,而有些金额则任意省略了任何货币指示。显然,这将被视为错误数据,应在源头进行修复。

如果您真的想处理这些错误数据,只需寻找加号或减号的存在。如果找到,则解析为OffsetDateTime。如果省略,则解析为LocalDateTime

if( input.contains( "+" ) || input.contains( "-" ) ) {
    OffsetDateTime odt = OffsetDateTime.parse( input ) ;
} else {
    LocalDateTime ldt = LocalDateTime.parse( input ) ;
}

或者,尝试将其解析为一种类型。如果抛出DateTimeParseException,请尝试其他类型。

如果您确定输入缺少其偏移量是针对特定区域或偏移量的,请应用该偏移量或区域。

ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;

如果您想在保持与 UTC 的偏移的同时丢失时区,以匹配您的其他 OffsetDateTime 对象,请调用 toOffsetDateTime

OffsetDateTime odt = zdt.toOffsetDateTime() ;

仅供参考,time zone 和单纯的offset 之间的区别......偏移量只是比(正)或落后(负)UTC 早几个小时分秒,prime meridian。时区更多。时区是特定地区人民使用的偏移量的过去、现在和未来变化的历史,由他们的政治家设定(并且经常改变!)。

【讨论】:

    【解决方案2】:

    您可以将具有偏移量的String 直接解析为OffsetDateTime,但不能使用没有偏移量或时区信息的String 解析。

    按照此处所示的方式进行操作:

    public static void main(String[] args) {
        String working = "2020-01-12T10:30-06:00";
        String notWorking = "2020-01-12T10:30";
    
        // directly parse the String with an offset to an OffsetDateTime
        OffsetDateTime offsetDateTime = OffsetDateTime.parse(working, 
                DateTimeFormatter.ISO_OFFSET_DATE_TIME);
        // parse the String without an offset to a LocalDateTime first
        LocalDateTime localDateTime = LocalDateTime.parse(notWorking, 
                DateTimeFormatter.ISO_LOCAL_DATE_TIME);
    
        // print them just to see the results
        System.out.println(offsetDateTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
        System.out.println(localDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
    
        // then convert the LocalDateTime to an OffsetDateTime by adding a ZoneOffset to it
        OffsetDateTime fromLocalDateTime = localDateTime.atOffset(ZoneOffset.of("-06:00"));
        // and print that
        System.out.println(fromLocalDateTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
    }
    

    结果输出是

    2020-01-12T10:30:00-06:00
    2020-01-12T10:30:00
    2020-01-12T10:30:00-06:00
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-24
      • 2016-07-28
      • 2018-06-02
      • 2014-05-24
      • 2011-05-18
      • 2019-09-07
      • 2015-08-26
      • 2020-03-15
      相关资源
      最近更新 更多