在测试环境中解析异常,而在Android环境中工作正常



我在Android中有一个非常简单的指令:

new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZ").parse("2019-07-24T21:27:09+02:00")

相同的指令在真实设备上运行时,会生成正确的输出:一个可以用Wed Jul 24 21:27:09 GMT+02:00 2019表示的 Date 对象

但是,当我在单元测试(使用 junit)中使用完全相同的指令时,它会给我java.text.ParseException.

我可以让它删除最后一个:(像这样,"2019-07-24T21:27:09+0200"),但我想知道为什么。我知道他们使用不同的JVM,但使用的Android API应该是相同的。

tl;博士

使用现代java.time类。切勿使用java.util.DateSimpleDateFormat

OffsetDateTime.parse( "2019-07-24T21:27:09+02:00" )

查看此代码在 IdeOne.com 实时运行。

java.time

您正在使用糟糕的旧日期时间类,这些类几年前被采用JSR 310的现代java.time类所取代。

这些java.time类内置于 Java 8 及更高版本以及 Android 26 及更高版本中。对于Java 6和7,请参阅ThreeTen-Backport中的向后移植,进一步适用于ThreeTenABP中的早期Android。

java.util.Date类被java.time.Instant取代,两者都代表UTC中的一个时刻。您的输入具有 UTC 偏移量,而不是零小时-分钟-秒,因此请使用OffsetDateTime类。

您的输入采用标准 ISO 8601 格式。java.time类在解析/生成字符串时默认使用 ISO 8601 格式。

OffsetDateTime odt = OffsetDateTime.parse( "2019-07-24T21:27:09+02:00" ) ;

查看此代码在 IdeOne.com 实时运行。

odt.toString(): 2019-07-24T21:27:09+02:00

要在 UTC 中查看同一时刻,请提取Instant。符合 ISO 8601 标准的字符串末尾的Z表示 UTC,发音为"祖鲁"。

Instant instant = odt.toInstant() ;

即时字符串(): 2019-07-24T19:27:09Z

实现方式各不相同

我可以让它删除最后一个:(像这样,"2019-07-24T21:27:09+0200"),但我想知道为什么。我知道他们使用不同的JVM,但使用的Android API应该是相同的。

(a)SimpleDateFormat&Date的行为没有实际意义,因为您不应该再使用这些类。他们真的那么糟糕。

(b) 在任何复杂的框架中,你可能会看到实现之间的细微差异,尤其是当由不同的团队构建时。旧日期时间类的规范未涵盖偏移量上的可选冒号等分钟详细信息。这就是生活。

我希望你会看到java.timeThreeTen-Backport的行为差异要少得多,因为它们都是由同一个人Stephen Colebourne领导的。我不知道与Android 26及更高版本捆绑在一起的java.time的Android实现,但我还没有听说过任何差异。

因此,出于这个原因,以及许多其他原因,我强烈建议使用java.time路线。

Android 上某些 Java 类的实现与 Oracle 的 JDK 不同。这可能是由于最近针对谷歌的诉讼。因此,一些Java API(主要是国际化和...日期格式)的行为可能有所不同。如果类的文档没有说明这是有效的格式,则可以提交错误。

相关内容

最新更新