Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/411.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么JavaScript可以处理2038年以后的时间戳?_Javascript_Php - Fatal编程技术网

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

为什么JavaScript可以处理2038年以后的时间戳?,javascript,php,Javascript,Php,我们知道,所有使用Javascript日期构造函数的日期都是从1970年1月1日00:00:00世界时(UTC)开始以毫秒为单位计算的,其中一天包含86400000毫秒。这意味着JS使用UNIX时间戳。我将计时器设置为2038年以后的日期(比如2039年11月14日),然后运行脚本: <script> var d = new Date(); alert(d.getFullYear()+" "+d.getMonth()+" "+d.getDate());

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

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

var d=新日期();
警报(d.getFullYear()+“”+d.getMonth()+“”+d.getDate());
它成功地向2039104发出警报,不像PHP打印“1903年10月9日07:45:59”


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

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

从(我的)重点:

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


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

32位PHP使用32位整数,其最大值将其在2038年表示的最后一个UNIX时间戳放入。这被广泛称为,并影响几乎所有使用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
正如你所看到的,这个数字不能保证准确无误。(实际返回的值与输入的值相同)为9007199254740992。根据我的转换测试,在285428751-11-12T07:36:32+00:00之前都很好:)

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

这意味着JS使用UNIX时间戳


附带说明:Unix时间戳是自1970年以来的秒数。自1970年以来,JS时间为毫秒。因此,JS时间戳不适合更早的32位int(但JS不使用32位int)

它可以。试用
新日期(8640000000000000)

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

公元275760年略高于2038年:)

阅读规范第15.9.1.1节

Date对象包含一个数字,该数字表示数据中的特定时刻 时间在一毫秒之内。这样的数字称为时间值。A. 时间值也可以是NaN,表示日期对象没有 表示特定的时间瞬间

自1970年1月1日起,时间以ECMAScript为单位,以毫秒为单位 UTC。时间值中的闰秒将被忽略。假设有 正是每天86400000毫秒。ECMAScript数值 可以表示从–9007199254740992到 9,007,199,254,740,992; 这个范围足以测量到的时间 任何瞬间的毫秒精度大约在 自协调世界时1970年1月1日起,向前或向后285616年

ECMAScript日期对象支持的实际时间范围为 稍微小一点:精确到100000000天到100000000天 相对于1970年1月1日开始时的午夜测量 UTC。这将提供8640000000000000毫秒到 UTC 1970年1月1日的任一侧

UTC 1970年1月1日凌晨的确切时刻 由值+0表示


我不明白为什么PHP不使用无符号整数。这将有效地将日期范围扩大一倍,对吗?@Alex,因为这样你就不能表示1970年之前的任何日期,因为PHP试图使类型保持简单,并且不想因为有符号整数和无符号整数之间的差异而困扰程序员,因为只使用无符号整数意味着你不能在PHP中表示任何负数,因为这只会将最后期限延长约70年,而不是完全解决它。@AlexW这是为了保留1970年之前的日期,1970年在UNIX时间戳中被视为一个纪元,对吗?还有一件事要问@deceze,因为长整型是4字节,浮点型也是4字节(尽管在C中),JS使用float而不是int时会怎么样?@rosemary会怎么样?不知道你在问什么。有趣的事实,
Number.MAX\u SAFE\u INTEGER
报告
9007199254740991
现在在chrome中。所以这个问题似乎已经解决了。值得注意的是,
新日期(Number.MAX\u SAFE\u INTEGER)
产生了“无效日期”。但是你绝对可以使用
Number.MAX\u SAFE\u INTEGER/2
,它可以帮助你度过公元144683年。希望这对于大多数用例来说已经足够好了,尽管我想你永远不会知道。如果说在公元144k年会出现任何语言,那就是JavaScript!☢️@mikermcneil是的,但你的答案也不准确,更新了我的答案以代表真正的极限:)谢谢你让我这么做:D