select unix_timestamp('2038-01-19')
返回2147472000
select unix_timestamp('2038-01-20')
返回0
我查看了2038
年问题。
我的linux操作系统是64位,安装的mysql版本也是64位。现在这个问题的解决方案是什么?
mysql --version
返回mysql Ver 14.14 Distrib 5.5.47, for Linux (x86_64) using readline 5.1
Php也是64位。
也试过BigInt,没有用(返回同样的东西)。
答案 0 :(得分:6)
简单地说,对于MySQL
,将日期存储为DATETIME
而不是TIMESTAMP
。
TIMESTAMP是4个字节,因此没有物理空间来存储比1970-1-1到2038-01-19之间更多的秒......
DATETIME的范围为1000-1-1到9999-12-31 ...
另请参阅此完整问题/答案:PHP & mySQL: Year 2038 Bug: What is it? How to solve it?
<强>更新强>:
我看到一种可能的替代方案,如果您无法更改字段类型,则 interpet 您的时间戳会有所不同......
我的意思是:如果您的应用程序将跟踪的第一个事件 - 比如说2000-1-1
,您可以在后端(或存储过程内部数据库),在阅读时为你的时间戳添加(2000-1-1
- 1970-1-1
)秒,并在阅读时减去相同的数量......这应该会给你30多年的“生存”。
答案 1 :(得分:3)
对于函数返回的数据类型,MySQL文档通常非常模糊,UNIX_TIMESTAMP()
也不例外。除非我们检查源代码,否则我认为我们只能做出有根据的猜测。
在Date and Time Type Overview,我们可以看到TIMESTAMP
数据类型本身具有不依赖于服务器架构的文档化范围:
范围是&#39; 1970-01-01 00:00:01.000000&#39; UTC到 &#39; 2038-01-19 03:14:07.999999&#39;世界标准时间。 TIMESTAMP值存储为 自纪元以来的秒数(&#39; 1970-01-01 00:00:00&#39; UTC)。一个 TIMESTAMP无法代表值&#39; 1970-01-01 00:00:00&#39;因为 相当于纪元0秒,值0 保留用于表示&#39; 0000-00-00 00:00:00&#39;,“零”TIMESTAMP 值。
即使我们确保通过正确的日期类型:
mysql> select
-> str_to_date('2038-01-20', '%Y-%m-%d'),
-> unix_timestamp(str_to_date('2038-01-20', '%Y-%m-%d'));
+---------------------------------------+-------------------------------------------------------+
| str_to_date('2038-01-20', '%Y-%m-%d') | unix_timestamp(str_to_date('2038-01-20', '%Y-%m-%d')) |
+---------------------------------------+-------------------------------------------------------+
| 2038-01-20 | 0 |
+---------------------------------------+-------------------------------------------------------+
1 row in set (0.01 sec)
...我们仍然得到0
,这是错误的愚蠢函数标志:
如果将超出范围的日期传递给UNIX_TIMESTAMP(),则返回0.
因此,可以安全地假设UNIX_TIMESTAMP()
返回TIMESTAMP
类型的值,因此不支持2038+。
简而言之:您必须在其他地方(即您的客户端代码)计算时间戳。由于有PHP标签:
$t = new DateTime('2038-01-20', new DateTimeZone('UTC'));
var_dump( $t->format('U') );
string(10)&#34; 2147558400&#34;
P.S。 MySQL fork,MySQL fork,具有相同的限制,但documents it更好:
MariaDB中的时间戳最大值为2147483647,相当于 到2038-01-19 05:14:07这是由于底层的32位 局限性。在超出此范围的日期使用该功能将导致 返回NULL。