我当时想使用TIMESTAMP来存储日期和时间,但是我读到它有2038年的限制。与其大量提出问题,不如将其分解成小部分,以便新手用户也易于理解。所以我的问题是:
- 2038年的问题到底是什么?
- 为什么会发生,何时发生?
- 我们该如何解决呢?
- 是否有使用它的其他可能的选择,而不会引起类似的问题?
- 当使用TIMESTAMP的现有应用程序真正发生时,我们该怎么办呢?
提前致谢。
我当时想使用TIMESTAMP来存储日期和时间,但是我读到它有2038年的限制。与其大量提出问题,不如将其分解成小部分,以便新手用户也易于理解。所以我的问题是:
提前致谢。
Answers:
我已将其标记为社区Wiki,因此随时可以编辑。
“ 2038年的问题(也称为Unix Millennium Bug,类似于Y2K问题的Y2K38)可能会导致某些计算机软件在2038年之前或之内发生故障。该问题影响所有将系统时间存储为带符号32的软件和系统。位整数,并将其解释为自1970年1月1日00:00:00 UTC以来的秒数。”
超越时代3时14分07秒UTC在星期二,2038 1月19日将“环绕”并为负数,这些系统将在1901年12月13日,解释为一个时间,而不是在2038年内部存储这是由于自UNIX时代(1970年1月1日00:00:00 GMT)以来的秒数已超过计算机的32位带符号整数的最大值这一事实。
DATE
列类型。如果需要更高的精度,请使用DATETIME
而不是TIMESTAMP
。请注意,DATETIME
列不存储有关时区的信息,因此您的应用程序将必须知道使用了哪个时区。尝试使用大类型在数据库中存储日期:64位就足够了-GNU C和POSIX / SuS或sprintf('%u'...)
PHP或BCmath扩展名中的long long类型。
因此,MySQL DATETIME的范围为1000-9999,而TIMESTAMP的范围仅为1970-2038。如果您的系统存储了出生日期,将来的远期日期(例如30年的抵押贷款)或类似的日期,那么您已经遇到了该错误。同样,如果这将成为问题,请不要使用TIMESTAMP。
在2038年,几乎没有PHP应用程序会出现,尽管很难预见,因为Web仍不是旧平台。
这是更改数据库表列以转换TIMESTAMP
为的过程DATETIME
。首先创建一个临时列:
# rename the old TIMESTAMP field
ALTER TABLE `myTable` CHANGE `myTimestamp` `temp_myTimestamp` int(11) NOT NULL;
# create a new DATETIME column of the same name as your old column
ALTER TABLE `myTable` ADD `myTimestamp` DATETIME NOT NULL;
# update all rows by populating your new DATETIME field
UPDATE `myTable` SET `myTimestamp` = FROM_UNIXTIME(temp_myTimestamp);
# remove the temporary column
ALTER TABLE `myTable` DROP `temp_myTimestamp`
资源资源
当使用UNIX时间戳记存储日期时,实际上是使用32位整数,该整数保留了从1970-01-01开始的秒数;见Unix时间
这个32位数字将在2038年溢出。这就是2038年的问题。
要解决该问题,您一定不能使用32位UNIX时间戳来存储日期-这意味着,在使用MySQL时,您不应使用TIMESTAMP
,而是DATETIME
(请参见10.3.1。DATETIME,DATE和TIMESTAMP类型):
DATETIME
当您需要包含日期和时间信息的值时,将使用该类型。支持的范围是'1000-01-01 00:00:00'
到'9999-12-31 23:59:59'
。该
TIMESTAMP
数据类型的范围是'1970-01-01 00:00:01'
为UTC'2038-01-19 03:14:07'
UTC。
为避免/解决该问题,您可以对应用程序进行
的(可能)最好的操作是不使用TIMESTAMP
,但DATETIME
对于必须包含不在1970年至2038年之间的日期的列。
不过,有一个小注意事项:从统计上讲,很有可能在2038年之前,您的应用程序已经被重写了好几次。^^因此,也许将来您不必处理日期,则您不必在当前版本的应用程序中解决该问题...
在Google上进行快速搜索可以解决这个问题:2038年的问题
http://en.wikipedia.org/wiki/Year_2038_problem具有大部分详细信息
综上所述:
1)+ 2)问题是许多系统将日期信息存储为32位带符号的int值,该值等于自1970年1月1日以来的秒数。可以像这样存储的最新日期是2038年1月19日星期二的03:14:07 UTC。发生这种情况时,int将“自动换行”并存储为负数,该负数将被解释为1901年的日期。然后,确切发生的情况因系统而异,但足以说这可能对他们中的任何一个都不好!
对于仅存储过去日期的系统,那么我想您不必担心一会儿!主要问题是将来使用日期的系统。如果您的系统需要使用未来28年的日期,那么您应该立即开始担心!
3)使用可用的其他日期格式之一,或移至64位系统并使用64位整数。或者,对于数据库,请使用其他时间戳格式(例如,对于MySQL,请使用DATETIME)
4)看3!
5)看4!;)
兄弟,如果您需要使用PHP来显示时间戳,这是不更改UNIX_TIMESTAMP格式的最佳PHP解决方案。
使用custom_date()函数。在其中,使用DateTime。这是DateTime解决方案。
只要您将UNSIGNED BIGINT(8)作为数据库中的时间戳记即可。只要您拥有PHP 5.2.0 ++
因为我不想升级任何东西,所以我要求后端(MSSQL)代替PHP做这项工作!
$qry = "select DATEADD(month, 1, :date) next_date ";
$rs_tmp = $pdo->prepare($qry);
$rs_tmp->bindValue(":date", '2038/01/15');
$rs_tmp->execute();
$row_tmp = $rs_tmp->fetch(PDO::FETCH_ASSOC);
echo $row_tmp['next_date'];
可能不是一种有效的方法,但是可以。