如何在不使用本地时区的情况下解析日期?

问题描述 投票:0回答:2

从服务器我得到以下值:

epochMillis=1556532279322
iso8601=2019-04-29T10:04:39.322Z

当我做serverTimeDateFormat.parse(iso8601)时,我得到Mon Apr 29 10:04:39 GMT+02:00 2019的结果

而对于serverTimeDateFormat.parse(iso8601).time,结果是1556525079322,这与我从服务器获得的结果(从UNIX时间落后2小时)不同,而我在timeZone + 2小时。

当我用serverTimeDatFormat.format(1556525079322)格式化它时,结果是2019-04-29T10:04:39.322Z我明白SimpleDateFormat正在使用当地时区,但为什么结果落后2小时,如何在不考虑时区的情况下解析Date?我不明白这一切的逻辑。

我的代码:

private val serverTimeDateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",Locale.ENGLISH)
val iso8601 = "2019-04-29T10:04:39.322Z" 
val epochMillis = 1556532279322
serverTimeDateFormat.parse(iso8601).time
android date kotlin simpledateformat
2个回答
1
投票

问题在于SimpleDateFormat的模式。最后,你有'Z',它表示要解析的日期字符串中应该有一个文字“Z”。但是,日期末的“Z”具有特殊含义,即it signifies the UTC timezone。因此,您应该将其解析为时区指示符,以便获得正确的日期值。您可以使用模式XXX执行此操作(请参阅JavaDocs)。

private val serverTimeDateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX",Locale.ENGLISH)
val iso8601 = "2019-04-29T10:04:39.322Z" 
print( serverTimeDateFormat.parse(iso8601).time ) // 1556532279322

Runnable example on pl.kotl.in


附录:虽然上述代码应该适合您,但如果可能的话,您应该考虑将ThreeTen Android Backport添加到您的项目中。这将使您可以访问由JSR310添加到Java / Kotlin的新时间类(在Android API >=26中也可以默认使用)。这些类通常更容易使用API​​,默认情况下使用ISO8601,因此您根本不需要任何格式化程序:

print( ZonedDateTime.parse(iso8601).toInstant().toEpochMilli() )

1
投票

Avoid legacy date-time classes

您正在使用几年前由JSR 310中定义的现代java.time类取代的可怕日期时间类。

Date::toString谎言

为什么结果落后2个小时

实际上并不落后两个小时。

问题是,虽然java.util.Date代表UTC的一个时刻,但它的toString方法动态应用JVM的当前默认时区,同时生成表示日期时间对象值的文本。善意的,这个反特征容易造成Date对象具有该时区的错觉。

换句话说,Date::toString谎言。在这些遗留类中发现的许多糟糕的设计决策之一。从不使用这些遗留类的众多原因之一。

java.time

Instant

从1970年的第一个时刻的UTC时代参考作为Instant解析你的毫秒数。

Instant instant = Instant.ofEpochMilli( 1556532279322 );

您的其他输入(标准ISO 8601字符串)也可以作为即时解析。

Instant instant = Instant.parse( "2019-04-29T10:04:39.322Z" ) ;

ZonedDateTime

要通过特定区域(时区)的人们使用的挂钟时间来查看同一时刻,请应用ZoneId来获取ZonedDateTime对象。

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ) ;

instantzdt对象都代表同一时刻。阅读同一时刻的两种方式,就像两个人在冰岛和魁北克通过电话交谈时,每个人都会看到墙上时钟的不同时间,同时同时浏览。

© www.soinside.com 2019 - 2024. All rights reserved.