本文介绍了无法解析ISO 8601格式的字符串,缺少冒号的冒号,到Java 8 Date的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对java 8日期格式/解析功能有点沮丧。我试图找到Jackson配置和 DateTimeFormatter 来解析2018-02-13T10:20:12.120 + 0000字符串到任何Java 8日期,并没有找到它。

这是 java.util.Date 示例工作正常:

I'm a little bit frustrated of java 8 date format/parse functionality. I was trying to find Jackson configuration and DateTimeFormatter to parse "2018-02-13T10:20:12.120+0000" string to any Java 8 date, and didn't find it.
This is java.util.Date example which works fine:

Date date = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSZZZ")
                      .parse("2018-02-13T10:20:12.120+0000");

相同的格式不适用于新的日期时间api

The same format doesn't work with new date time api

ZonedDateTime dateTime = ZonedDateTime.parse("2018-02-13T10:20:12.120+0000",
                   DateTimeFormatter.ofPattern("yyyy-MM-dd'T'hh:mm:ss.SSSZZZ"));

我们应该能够以适合FE UI应用的任何格式格式化/解析日期。也许我误解或误解了一些东西,但我认为 java.util.Date 提供更多格式灵活性并且更易于使用。

We should be able to format/parse date in any format suitable for FE UI application. Maybe I misunderstand or mistake something, but I think java.util.Date gives more format flexibility and easier to use.

推荐答案

tl; dr



直到bug被修复:

tl;dr

Until bug is fixed:

OffsetDateTime.parse(
    "2018-02-13T10:20:12.120+0000" ,
    DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ss.SSSX" )
)

当错误修复时:

OffsetDateTime.parse( "2018-02-13T10:20:12.120+0000" )



详细信息



您使用的是错误的类。

Details

You are using the wrong classes.

避免使用麻烦的旧遗留类,例如日期日历 SimpleDateFormat的。现在取代了类很好,它是java.time的一部分。但它适用于全时区。您的输入字符串只有一个。相比之下,全时区是对不同时间点,过去,现在和将来的区域有效的偏移的集合。例如,在北美大部分地区使用夏令时(DST)时,每年两次的偏移量会在春季变小,因为我们将时钟向前移动一小时,而在秋季我们将时钟向后移动时恢复到更长的值小时。

The ZonedDateTime class you used is good, it is part of java.time. But it is intended for a full time zone. Your input string has merely an offset-from-UTC. A full time zone, in contrast, is a collection of offsets in effect for a region at different points in time, past, present, and future. For example, with Daylight Saving Time (DST) in most of North America, the offsets change twice a year growing smaller in the Spring as we shift clocks forward an hour, and restoring to a longer value in the Autumn when we shift clocks back an hour.

仅限偏移而不是时区,请使用 class。

For only an offset rather than a time zone, use the OffsetDateTime class.

您的输入字符串符合标准。解析/生成字符串时,java.time类在默认情况下使用标准格式。因此无需指定格式化模式。

Your input string complies with the ISO 8601 standard. The java.time classes use the standard formats by default when parsing/generating strings. So no need to specify a formatting pattern.

OffsetDateTime odt = OffsetDateTime.parse( "2018-02-13T10:20:12.120+0000" );

好吧,应该有效。遗憾的是,Java 8中存在错误(至少通过Java 8 Update 121),该类无法解析在小时和分钟之间省略冒号的偏移量。所以这个bug会在 +0000 上叮咬,但不会 +00:00 。因此,在修复程序到达之前,您可以选择两种解决方法:(a)hack,操作输入字符串,或(b)定义显式格式化模式。

Well, that should have worked. Unfortunately, there is a bug in Java 8 (at least up through Java 8 Update 121) where that class fails to parse an offset omitting the colon between hours and minutes. So the bug bites on +0000 but not +00:00. So until a fix arrives, you have a choice of two workarounds: (a) a hack, manipulating the input string, or (b) define an explicit formatting pattern.

hack:操纵输入字符串以插入冒号。

The hack: Manipulate the input string to insert the colon.

String input = "2018-02-13T10:20:12.120+0000".replace( "+0000" , "+00:00" );
OffsetDateTime odt = OffsetDateTime.parse( input );

更强大的解决方法是在 DateTimeFormatter中定义和传递格式化模式 object。

The more robust workaround is to define and pass a formatting pattern in a DateTimeFormatter object.

String input = "2018-02-13T10:20:12.120+0000" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ss.SSSX" );
OffsetDateTime odt = OffsetDateTime.parse( input , f );



顺便提一下,这里有一个提示:我发现有很多协议和库,如果你的生活更轻松偏移总是有冒号,总是有小时和分钟(即使分钟为零),并且总是使用填充零( -05:00 而不是 -5 )。

By the way, here is a tip: I have found that with many protocols and libraries, your life is easier if your offsets always have the colon, always have both hours and minutes (even if minutes are zero), and always use a padding zero (-05:00 rather than -5).

如果您想使用始终为UTC(并且您应该)的值,请提取 Instant 对象。

If you want to work with values that are always in UTC (and you should), extract an Instant object.

Instant instant = odt.toInstant();



ZonedDateTime



如果你想透过一些地区的镜头来观看那个时刻的,应用时区。

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = odt.atZoneSameInstant( z );

查看此。

许多问题在许多答案中都涵盖了很多次。请在发布前彻底搜索Stack Overflow。你会发现很多甚至数百个例子。

All of this has been covered many times in many Answers for many Questions. Please search Stack Overflow thoroughly before posting. You would have discovered many dozens, if not hundreds, of examples.

框架内置于Java 8及更高版本中。这些类取代了麻烦的旧日期时间类,例如,,& 。

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

项目,现已进入 ,建议迁移到 classes。

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

要了解更多信息,请参阅。并搜索Stack Overflow以获取许多示例和解释。规范是。

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

您可以直接与数据库交换 java.time 对象。使用符合 / jeps / 170rel =nofollow noreferrer> JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql。* 类。

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

从哪里获取java.time班?

Where to obtain the java.time classes?


  • ,, ,以及之后


    • 内置。

    • 带有捆绑实现的标准Java API的一部分。

    • Java 9添加了一些小功能和修复。

    • Java SE 8, Java SE 9, Java SE 10, and later
      • Built-in.
      • Part of the standard Java API with a bundled implementation.
      • Java 9 adds some minor features and fixes.

      • 大部分java.time功能都被反向移植到Java 6& 7 。

      • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.

      • java.time 类的Android捆绑包实现的更高版本。

      • 对于早期的Android(< 26),项目适应(如上所述)。请参阅。

      • Later versions of Android bundle implementations of the java.time classes.
      • For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….

      项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在这里找到一些有用的课程,例如,,,。

      这篇关于无法解析ISO 8601格式的字符串,缺少冒号的冒号,到Java 8 Date的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-05 05:09