8

我们知道,所有使用 Javascript Date 构造函数的日期都是从 1970 年 1 月 1 日 00:00:00 世界标准时间 (UTC) 开始以毫秒为单位计算的,一天包含 86,400,000 毫秒。这意味着 JS 使用 UNIX 时间戳。我将计时器设置为 2038 年之后的日期(比如 2039 年 11 月 14 日)并运行脚本:

    <script>
      var d = new Date();
      alert(d.getFullYear()+" "+d.getMonth()+" "+d.getDate());
    </script>

与打印“9 Oct, 1903 07:45:59”的 PHP 不同,它成功警告 2039 10 14

JS如何处理这个?解释很感激,因为我很困惑!

4

5 回答 5

15

32 位 PHP 使用 32 位整数,其最大值将它们表示的最后一个 UNIX 时间戳放在 2038 年。这被广泛称为Y2K38 问题,并且几乎影响所有使用 UNIX 时间戳的 32 位软件。迁移到 64 位或与其他时间戳表示一起工作的库(在 PHPDateTime类的情况下)解决了这个问题。

Javascript没有整数,只有浮点数,它没有固有的最大值(但作为回报,精度较低)。

于 2013-11-14T14:46:42.220 回答
5

Javascript 没有整数,只有浮点数(可以在标准文档中找到详细信息)。

这意味着您可以表示一些非常大的数字,但要以精度为代价。一个简单的测试是这样的:

i = 1384440291042
 => 1384440291042
i = 13844402910429
 => 13844402910429
i = 138444029104299
 => 138444029104299
i = 1384440291042999
 => 1384440291042999
i = 13844402910429999
 => 13844402910430000
i = 138444029104299999
 => 138444029104300000
i = 1384440291042999999
 => 1384440291043000000
i = 13844402910429999999
 => 13844402910430000000

如您所见,不能保证该数字保持准确。javascript 中整数精度的外部限制(实际上您将获得与输入相同的值)为 9007199254740992。根据我的转换测试,这在 285428751-11-12T07:36:32+00:00 之前都很好: )

简单的答案是 Javascript 在内部使用比用于 C 风格 epoc 的 longint(4 字节,32 位)更大的数据类型......

于 2013-11-14T14:55:10.497 回答
2

它可以。试用new Date(8640000000000000)

9 月 13 日星期六 275760 03:00:00 GMT+0300(东欧夏令时间)

275760 年有点超出 2038 年 :)

阅读规范部分 15.9.1.1

http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.1

Date 对象包含一个数字,该数字指示特定的瞬间,精确到毫秒。这样的数字称为时间值。时间值也可能是 NaN,表示 Date 对象不代表特定的时间瞬间。

自 1970 年 1 月 1 日 UTC 以来,时间在 ECMAScript 中以毫秒为单位进行测量。在时间值中,闰秒被忽略。假设每天正好有 86,400,000 毫秒。ECMAScript Number 值可以表示从 –9,007,199,254,740,992 到 9,007,199,254,740,992 的所有整数;该范围足以测量从 1970 年 1 月 1 日 UTC 起大约 285,616 年(向前或向后)内的任何时刻的毫秒精度。

ECMAScript Date 对象支持的实际时间范围略小:相对于 1970 年 1 月 1 日 UTC 开始时的午夜,精确地测量 –100,000,000 天到 100,000,000 天。这为 1970 年 1 月 1 日 UTC 的任一侧提供了 8,640,000,000,000,000 毫秒的范围。

UTC 时间 1970 年 1 月 1 日开始的午夜的确切时刻由值 +0 表示。

于 2019-02-21T08:23:30.213 回答
1

2038 年问题仅适用于 PHP 和其他一些系统使用的签名 32 位时间戳。带符号的 32 位时间戳的范围以 2038 年的秒数结束。

来自维基百科文章(强调我的):

2038 年问题可能会导致某些计算机软件在 2038 年附近的某个时间点出现故障。该问题会影响所有将系统时间存储为有符号 32 位整数并将此数字解释为自 00 以来的秒数的软件和系统1970 年1月 1 日星期四 :00:00 UTC。1 可以这种方式表示的最远时间是 2038 年 1 月 19 日星期二 03:14:07 UTC。[2] ...这是由整数溢出引起的。计数器“用完”可用数字,而是“增加”符号位,并报告最大负数(继续向上计数,向零方向计数)。由于计算错误,这可能会给这些系统的用户带来问题。

将时间戳存储在具有更大范围的变量中可以解决该问题。

于 2013-11-14T14:46:27.560 回答
1

这意味着 JS 使用 UNIX 时间戳。

只是一个旁注:Unix时间戳是1970年以来的秒数。JS时间是1970年以来的毫秒数。所以JS时间戳不适合更早的32位int(但JS不为此使用32位int)

于 2018-12-12T09:07:33.197 回答