在Javascript和MongoDB中使用UTC日期

时间:2014-10-22 11:37:26

标签: java javascript mongodb date momentjs

我在使用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"例如,它可能会把它变成正确的日期......

任何人都可以确认这是要走的路吗?

谢谢!

1 个答案:

答案 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应用程序,因为它很容易获得并避免各种转换格式问题。