使用Javascript和MongoDB中的UTC日期

Working with UTC Dates in Javascript and MongoDB

本文关键字:UTC 日期 中的 MongoDB Javascript 使用      更新时间:2023-09-26

我在正确使用UTC日期时遇到问题,不知道是否有一种常见的方法来处理此问题。

基本上,我有一个javascript日期选择器,可以在其中选择日期。例如:

 2014-10-15

当它用JSON.stringify()转换成字符串时,我得到的是:

 2014-10-14T22:00:00+0200

我认为这是正确的,因为日期被转换为UTC日期。

当日期到达我的java(jersey)REST接口时,它看起来如下:

 2014-10-14T22:00:00.000Z

日期看起来是一样的,但+0200已经不在了。可能是问题的原因。

下一步是将日期保存到我的mongo数据库中,然后该数据库存储如下日期:

 2014-10-14 20:00:00.000Z

另外两个小时被取消了,我认为这是因为日期"再次"被转换为UTC。

我现在的问题是,如果我重新加载页面,我的输入字段现在显示:

2014-10-14

而不是2014-10-15。

如果我手动更改数据库中的日期,并再次添加2个小时以"2014-10-14T22:00:00.000Z"结束,则该日期将再次正确显示在前端-该日期现在正确表示为本地时间,因为2014-10-14T22-00:000Z之上的2个小时将使2014-10-15再次出现。

我的问题是:

我需要在哪里进行更改以防止这种情况发生?

a) 我在前端只使用本地时间,所以mongodb只转换为UTC。这对我来说听起来不太安全,因为我确信当从不同时区呼叫客户时,这会引起问题。

b) 我只使用UTC日期,但我需要以某种方式告诉mongodb日期已经是UTC,因此无需再次转换。

如有任何帮助,我们将不胜感激。

谢谢,Michael

编辑

我想我现在可能更进一步了。我可以告诉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驱动程序)再次将日期转换为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:0:00-0600",它可能也会把它变成正确的日期。。。

有人能确认这是要走的路吗?

谢谢!

希望这些信息能有所帮助。

MongoDB数据库不进行转换。它只是假设收到的日期是UTC时间。java驱动程序从日期对象获取UTC时间(以毫秒为单位)。以下代码来自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 Object,并将其保存到数据库中,以检查是否有进一步的转换。(比较时请注意java应用程序的时区)


现在,重点是:如果您得到2014-10-14T22:00:00+02000,那么源应该是2014-20110-15T000:00:000+0400201410-15T02:000+0600等。这意味着在调用javascript日期选择器和JSON.stringify()时使用了不同的时区。

当您将字符串"2014-10-14T22:00:00+0200"发送到java应用程序并由SimpleDateFormat解析时,请确保模式与数据一致(使用新的SimpleDateFormat("yyyy-MM-dd-'TH:MM:ssz")。不要忘记最后一个字符z,否则+0200将被删除,字符串的其余部分将根据java应用程序时区的时区进行解析。)

当使用SimpleDateFormat对输出进行双重检查时,最好在将日期对象传递给System.out.print()之前创建另一个新的SimpleDateFormat("yyyy-MM-dd'TH:MM:ssz")来格式化日期对象,因为按时区比较更容易。

如果可能的话,我建议您将UTC毫秒发送到java应用程序,因为它很容易获得并避免各种转换格式问题。