2038年问题 - 64位(Linux OS,php,mysql)

时间:2016-04-22 12:11:46

标签: php mysql linux

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,没有用(返回同样的东西)。

2 个答案:

答案 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。