Java/JavaScript 日期:这是真的吗?

10
假设用户的浏览器所在时区与应用服务器不同,我通过使用JavaScript的date.getTime()方法在客户端对日期进行序列化。然后,我将结果毫秒数通过Json发送,并在服务器端调用new Date(millisecondsFromJS)创建一个Java Date对象。我将其存储在MySql中,检索它,再次通过调用Java的date.getTime()对其进行序列化,并通过Json再次发送到客户端。
如果我使用这些毫秒数创建JavaScript Date对象,将会得到原始日期吗?我已经成功地完成了这个过程,但是客户端和服务器当前处于相同的时区。如果时区不同,日期是否会在这个过程中被破坏,我不确定。
据我所知,使用getTime()返回的时间独立于时区。例如,如果用户捕获了2012年7月17日下午4:39 CST,服务器可能将其存储为2012年7月17日晚上11:39 CEST,但是一旦服务器将其转换为GMT自1970年1月1日零点以来的毫秒数,客户端从这些毫秒数创建日期后,将成功重建原始的2012年7月17日下午4:39 CST。这是真的吗?

我认为使用包含日期相对于时区偏移量的文本形式会更安全。这样,无论客户端和服务器位于哪个时区,它们都可以准确地知道时间值是什么。或者,如果您想使用毫秒,则应标准化为GMT毫秒,而不是本地时区的毫秒。 - jfriend00
除此之外,Unix时间是基于协调世界时(UTC)的,要获取日期的ISO表示形式:var now = new Date(); 然后 now.toISOString(); - Wolfram
Java的getTime()毫秒是格林威治标准时间,但我不确定JavaScript的是否也是。 - JayPea
1
@JayPea https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Date/getTime - Esailija
2个回答

12

这篇文章《Dropbox 的扩展经验教训——第一部分》中提供了一些很好的建议:

内部全部采用 UTC 时间制!服务器时间、数据库内容等都要使用 UTC。这样做不仅可以避免夏令时等问题,而且可以避免某些软件无法正确处理非 UTC 时间的情况。我们墙上挂着一个设置为 UTC 的时钟。当你需要向用户显示时间时,只需在最后一步进行时区转换即可。


将 Unix 时间戳(毫秒)发送到服务器,就可以知道用户选择的时间点。然后在服务器上处理所有内容并返回毫秒整数给客户端,均在 UTC 时间制下完成。

客户端/JavaScript:

var date = new Date();
var clientMilliseconds = date.getTime();
// send clientMilliseconds to server

服务器/Java:

Date date = new Date(clientMilliseconds);
// store the date, then get it back
long serverMilliseconds = date.getTime();
// send serverMilliseconds back to client

客户端 / JavaScript:

var date = new Date(serverMilliseconds);
// If receiving the error "Invalid Date", serverMilliseconds
// needs to be converted to an Integer. Consider:
// parseInt: parseInt(serverMilliseconds, 10)
// unary +:  (+serverMilliseconds)

在此过程中,服务器和客户端上的date对象都将反映各自的时区,因此如果您查看两者,它们可能看起来不同,但如果您使用相同的时区将它们转换回UTC,那么它们并不不同。


所以回答你的问题:

如果我使用这些毫秒创建JavaScript Date对象,结果会是原始日期吗?

是的。

Java的Date(long date)构造函数getTime()方法使用Unix时间毫秒。JavaScript的getTime()Date构造函数也是如此。除了协调世界时(GMT/UTC)之外,不应涉及任何其他时区。


2

有一些问题

  • 客户端位于不同的时区。如果使用 .getTime(), .valueOf() 等方法,这并不是一个问题,因为它们使用自纪元以来的毫秒数(根据UTC)。
  • 真正的问题是客户端的时钟可能会偏差。例如,如果有人将他们的计算机时间向后调整,以避免注册某些程序,那么它将导致客户端生成错误的时间戳。
  • 由于时钟不准确,它们也可能有一小部分偏差。

您可以通过从服务器发送时间戳,然后将其与客户端生成的时间戳进行比较,以获取偏差偏移量来解决此问题。然后,将此偏差偏移量应用于在客户端上生成的所有 new Date.getTime()。但是,如果客户端在使用您的页面时更改系统时间,则此方法将无效。


谢谢,你提到的第二个问题在这种情况下并不是一个问题,因为日期来自日期选择器,不是表示当前时间点。所以Java和JavaScript中的getTime()将返回相同的值? - JayPea
@JayPea 不会,如果客户端的系统时钟有偏差的话。例如,在stackoverflow聊天中,他们为我生成了一个偏移量为5.5秒的偏斜度。 - Esailija
我想到了另外一件事... 如果这个程序能够正常工作,但是服务器突然被移动到另一个时区,那么当它从MySql中检索日期时,会应用不同的时区,用户将得到错误的日期。 - JayPea
1
@JayPea 操作时间戳和UTC日期。另外,如果可以避免使用在客户端生成的时间戳,那当然最好不要用。 - Esailija

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接