为什么 JavaScript 可以处理 2038 年以后的时间戳

Why can JavaScript handle timestamps beyond 2038?

本文关键字:时间戳 处理 JavaScript 为什么 2038      更新时间:2023-09-26

众所周知,所有使用 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>

它成功提醒 2039 10 14,不像 PHP 打印"9 Oct, 1903 07:45:59"

JS如何处理这个问题?感谢解释,因为我感到困惑!

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

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

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 位)更大......

可以。试用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 日起,时间以毫秒为单位以毫秒为单位 世界协调时。在时间值中,闰秒将被忽略。假设有 正好是每天 86,400,000 毫秒。ECMAScript 数值 可以表示从 –9,007,199,254,740,992 到 9,007,199,254,740,992;此范围足以测量时间 毫秒精度,适用于大约在 285,616 年,向前或向后,从 1970 年 1 月 1 日 UTC 开始。

ECMAScript Date 对象支持的实际时间范围为 稍小:正好是 –100,000,000 天到 100,000,000 天 相对于 1970 年 1 月 1 日午夜的测量值 世界协调时。这给出了 8,640,000,000,000,000,000 毫秒的范围 1970 年 1 月 1 日 UTC 的两侧。

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

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

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

2038 年的问题仅适用于 PHP 和其他一些系统使用的带符号 32 位时间戳。有符号的 32 位时间戳的范围随着 2038 年的秒数而耗尽。

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

2038年

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

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