MySQL文档通常对函数返回的数据类型非常模糊,UNIX_TIMESTAMP()
也不例外。除非我们检查源代码,否则我们只能做出有根据的猜测。
在日期和时间类型概述中,我们可以看到TIMESTAMP
数据类型本身具有一个已记录的范围,不依赖于服务器架构:
范围是从“1970-01-01 00:00:01.000000”UTC到“2038-01-19 03:14:07.999999”UTC。 TIMESTAMP值存储为自纪元(“1970-01-01 00:00:00”UTC)以来的秒数。 TIMESTAMP无法表示值“1970-01-01 00:00:00”,因为它相当于自纪元以来的0秒,值0保留用于表示“0000-00-00 00:00:00”,即“零”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') );
2147558400
P.S. MariaDB,MySQL的分支,有相同的限制,但它文档得更好:
MariaDB中的时间戳最大值为2147483647,相当于2038-01-19 05:14:07。这是由于底层32位限制造成的。在超出此日期的日期上使用该函数将导致返回NULL。
UNIX_TIMESTAMP()
函数需要一个日期作为参数。如果你传递的是字符串,那么程序会依赖于隐式类型转换。如果你事先明确了要操作的具体日期类型,那么你可能会得到一个更加清晰的解决方案。 - Álvaro González