我在使用UTC-Dates时遇到了问题,并且想知道是否有一种常见的处理方法。
基本上我有一个javascript datepicker,我可以选择一个日期。例如:
2014-10-15
当它转换为带有JSON.stringify()的字符串时,我最终得到:
2014-10-14T22:00:00+0200
我假设这是正确的,因为日期会转换为UTC日期。
当日期到达我的java(泽西岛)REST界面时,它看起来如下:
2014-10-14T22:00:00.000Z
日期似乎相同,但+0200不再存在。可能导致问题。
下一步是将日期保存到我的mongo数据库,然后存储日期,如下所示:
2014-10-14 20:00:00.000Z
另外2个小时已被取消,我假设这是因为日期正在转换为UTC"再次"。
我现在遇到的问题是,如果我重新加载页面,我的输入字段现在说:
2014-10-14
而不是2014-10-15。
如果我手动更改数据库中的日期并再次添加2小时以结束" 2014-10-14T22:00:00.000Z",则日期会再次正确显示在前端 - 日期现在正确表示为当地时间,因为在2014-10-14T22:00:00.000Z之上的2小时再次使2014-10-15。
我的问题是:
我需要在哪里进行更改才能防止这种情况发生?
a)我只在前端使用本地时间,因此mongodb只能转换为UTC。这对我来说听起来不太安全,因为我确信当从不同的时区调用客户端时会出现问题。
b)我只使用UTC日期,但我需要告诉mongodb日期已经是UTC,因此无需再次转换。
非常感谢任何帮助。
谢谢, 迈克尔
修改
我想我现在可能更进一步了。我可以告诉json反序列化器可以预期哪种日期格式。我已将此配置为:
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
如果我手动测试日期格式,我最终会用
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
System.out.println(sdf.parse("2014-10-14T22:00:00+0200"));
产生
Tue Oct 14 22:00:00 CEST 2014
所以难怪mongodb(或mongo-bson-driver)再次将日期转换为UTC。
如果我这样做:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); // Removed the "Z"
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(sdf.parse("2014-10-14T22:00:00+0200"));
它正确地提出:
Wed Oct 15 00:00:00 CEST 2014
当从mongodb驱动程序完成转换时,它可能会将其转换为" 2014-10-14T22:00:00 + 0200"再次哪个是正确的。
不确定这是否是最佳方式...如果客户日期在另一个时区,我会遇到问题吗?我想不是因为如果它是" 2014-10-15T06:00:00-0600"例如,它可能会把它变成正确的日期......
任何人都可以确认这是要走的路吗?
谢谢!
答案 0 :(得分:1)
希望这些信息可以提供帮助。
MongoDB数据库没有进行转换。它只是假设收到的日期是UTC时间。它是从日期对象获得UTC时间(以毫秒为单位)的java驱动程序。以下代码来自 mongo-java-driver-2.12.3.jar 的 BasicBSONEncoder.java 。
protected void putDate( String name , Date d ){
_put( DATE , name );
_buf.writeLong( d.getTime() ); // d.getTime() Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
}
如果您对此仍然有疑问,可以直接在java代码中新建一个Date对象并将其保存到数据库以检查是否有任何进一步的转换。 (比较时注意java应用程序的时区)
现在,重点是:如果你得到 2014-10-14T22:00:00 + 0200 ,那么来源应 2014-10-15T00:00:00 + 0400 ,或 2014-10-15T02:00:00 + 0600 等。这意味着在调用javascript datepicker和JSON.stringify()之间使用了不同的时区。
当你发送字符串" 2014-10-14T22:00:00 + 0200"对于java应用程序并由SimpleDateFormat
解析,请确保模式与数据一致(使用新的SimpleDateFormat(" yyyy-MM-dd' T' HH:mm:ss z ")。不要忘记最后一个字符 z ,否则将丢弃+0200,并根据时区解析字符串的剩余部分你的java应用程序时区。)
当您使用SimpleDateFormat
仔细检查输出时,您最好创建另一个新的SimpleDateFormat(" yyyy-MM-dd' T' HH:mm:ssz&# 34;)在将日期对象传递给System.out.print()
之前对其进行格式化,因为它更容易按时区进行比较。
如果可能的话,我建议你将UTC毫秒发送给java应用程序,因为它很容易获得并避免各种转换格式问题。