我们知道使用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如何处理这个问题?我感到很困惑,感激不尽!
答案 0 :(得分:11)
32位PHP使用32位整数,其最大值放置了2038年可以表示的最后一个UNIX时间戳。这就是众所周知的Y2K38 problem,几乎影响所有使用UNIX时间戳的32位软件。移动到64位或与其他时间戳表示一起使用的库(在PHP的情况下为DateTime
类)解决了这个问题。
Javascript没有整数,只有floats,它没有固有的最大值(但反过来精度较低)。
答案 1 :(得分:4)
Javascript没有整数,只有浮点数(详细信息可以在the standards document中找到)。
这意味着您可以代表一些非常大的数字,但代价是精确度。一个简单的测试就是:
i = 1384440291042
=> 1384440291042
i = 13844402910429
=> 13844402910429
i = 138444029104299
=> 138444029104299
i = 1384440291042999
=> 1384440291042999
i = 13844402910429999
=> 13844402910430000
i = 138444029104299999
=> 138444029104300000
i = 1384440291042999999
=> 1384440291043000000
i = 13844402910429999999
=> 13844402910430000000
正如您所看到的,这个数字并不能保证准确。 The outer limits of integer precision in javascript(你实际上会得到你输入的相同值)是9007199254740992.根据我的转换测试,这将是好的,直到285428751-11-12T07:36:32 + 00:00:)
简单的答案是Javascript内部使用的数据类型比用于C风格epoc的longint(4字节,32位)更大......
答案 2 :(得分:1)
2038年问题仅适用于签名的32位时间戳,PHP和其他一些系统使用这些时间戳。带符号的32位时间戳的范围在2038年以秒为单位。
来自Wikipedia article(强调我的):
2038年的问题可能导致某些计算机软件在2038年附近的某个时刻出现故障。该问题会影响所有将系统时间存储为带符号的32位整数的软件和系统。将此数字解释为自1970年1月1日星期四00:00:00 UTC以来的秒数。1可以用这种方式表示的最晚时间是2038年1月19日星期二03:14:07 UTC。 [2] ... 这是由整数溢出引起的。计数器“耗尽”可用数字,“增加”符号位,并报告最大负数(继续向上计数,向零) 。由于错误的计算,这可能会给这些系统的用户带来问题。
在具有更大范围的变量中存储时间戳可以解决问题。
答案 3 :(得分:0)
这意味着JS使用UNIX时间戳。
请注意:Unix时间戳自1970年以来为秒。JS时间自1970年以来为毫秒。因此JS时间戳不适合更早的32位int(但JS对此不使用32位int)
答案 4 :(得分:0)
JavaScript的常量为Number.MAX_SAFE_INTEGER
它的值是9007199254740991,所以这也是UNIX时间戳的最大安全值。 9007199254740991秒是〜285616年。 因此,JS可以处理Unix时间戳,直到1月1日大约287586。
哪个足够好。在大多数情况下:-)
在此上下文中,安全是指能够精确表示整数并正确比较它们的能力。例如,Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2将计算为true,这在数学上是不正确的。