跨时区的JodaTime de / serialization会破坏代码

时间:2013-09-20 17:09:39

标签: serialization deserialization jodatime

在部署到生产环境之后,我的代码崩溃了,经过相当多的bug追逐,我发现JodaTime在生产中处理de / serialization的方式不同于dev环境。显然,生产服务器位于另一个时区。

开发中的反序列化和序列化:

scala> val input = "2013-09-07T17:11:03.117+03:00"
input: String = 2013-09-07T17:11:03.117+03:00

scala> val thisIsDev = new DateTime(input).toString()
thisIsDev: String = 2013-09-07T17:11:03.117+03:00

scala> input == thisIsDev
res3: Boolean = true

注意ISO8601字符串末尾的+03:00,无论是最初还是重新序列化后。现在这就是生产中发生的事情,它位于+0时区:

scala> val sameInput = "2013-09-07T17:11:03.117+03:00"
sameInput: String = 2013-09-07T17:11:03.117+03:00

scala> val thisIsProd = new DateTime(sameInput).toString()
thisIsProd: String = 2013-09-07T14:11:03.117Z

scala> sameInput == thisIsProduction
res1: Boolean = false

如您所见,+03:00已被解除,日期字符串的格式更改了时区。

这是一个解决的问题吗?建议?

修改:

为了澄清,问题在于,如果我序列化,更改时区(例如,转到不同的服务器),然后反序列化并重新序列化,我最终得到的字符串不同于我的开头。这就是我的作品破产的原因,但我的测试没有。我花了一段时间来弄明白这一点。

注意:这些ISO8601字符串用于CouchDb服务器,它按字母顺序对它们进行排序,这就是为什么我不能使用JodaTime方法进行比较。

编辑2:

理想情况下,答案将建议如何将ISO8601字符串反序列化为DateTime对象,而不会丢失时区信息(在不同的时区)。

编辑2.1: I opened a relevant question and got the solution I needed here.

1 个答案:

答案 0 :(得分:0)

鉴于您编辑的问题,最简单的答案是强制每个日期时间都在同一时区,例如

scala> new DateTime("2013-09-07T17:11:03.117+03:00").withZone(DateTimeZone.UTC)
res1: org.joda.time.DateTime = 2013-09-07T14:11:03.117Z

scala> new DateTime("2013-09-07T14:11:03.117Z").withZone(DateTimeZone.UTC)
res2: org.joda.time.DateTime = 2013-09-07T14:11:03.117Z

但请注意,在这种情况下,您将丢失信息,即日期所在的时区。如果您将日期用于内部目的(例如查找新项目),那么这并不重要,如果您要将数据发送回用户,那么您需要找到另一种解决方案。