代码之家  ›  专栏  ›  技术社区  ›  Devner

PHP和mySQL:2038年错误:是什么?如何解决?

  •  84
  • Devner  · 技术社区  · 16 年前

    我想用时间戳来存储日期+时间,但我读到它有2038年的限制。我宁愿把问题分成几个小部分,以便新手也能容易地理解,而不是成堆地问我的问题。因此,我的问题是:

    1. 为什么会发生,发生时会发生什么?
    2. 我们如何解决它?
    3. 我们可以对使用时间戳的现有应用程序做些什么来避免所谓的问题,当它真正发生时?

    提前谢谢。

    6 回复  |  直到 16 年前
        1
  •  161
  •   Corey Ballou    9 年前

    我已将此标记为社区wiki,因此请随意编辑。

    2038年的问题到底是什么?

    “2038年的问题(也被称为Unix千年虫,Y2K38与Y2K问题类似)可能会导致某些计算机软件在2038年之前或之后出现故障。该问题影响到所有将系统时间存储为有符号32位整数的软件和系统,并将该数字解释为UTC 1月1日00:00:00以来的秒数, 1970."


    超越


    我们如何解决它?


    是否有任何可能的替代方案来使用它,而这些替代方案不会造成类似的问题?

    尽可能使用大类型在数据库中存储日期:64位就足够了——GNU C和POSIX/SuS中的长类型,或者 sprintf('%u'...) 在PHP或BCmath扩展中。


    那么MySQL呢 DATETIME


    我们可以对使用时间戳的现有应用程序做些什么来避免所谓的问题,当它真正发生时?

    2038年,很少有PHP应用程序仍然存在,尽管很难预见web还不是一个遗留平台。

    下面是更改数据库表列以进行转换的过程 日期时间

    # 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`
    

        2
  •  15
  •   Pascal MARTIN    16 年前

    当使用UNIX时间戳存储日期时,实际上使用的是32位整数,用于记录自1970-01-01以来的秒数;看见 Unix Time

    这个32位的数字将在2038年溢出。这就是2038年的问题。


    为了解决这个问题,您不能使用32位UNIX时间戳来存储日期——这意味着,在使用MySQL时,您不应该使用 TIMESTAMP 但是 DATETIME (见 10.3.1. The DATETIME, DATE, and TIMESTAMP Types ) :

    这个 日期时间 当您 需要同时包含日期和时间的值 时间信息。支持的范围 '1000-01-01 00:00:00' '9999-12-31 23:59:59' .

    这个 时间戳 数据类型有一个范围 属于 '1970-01-01 00:00:01' UTC至 '2038-01-19 03:14:07' UTC。


    这个 (可能) 为了避免/修复该问题,您可以对应用程序做的最好的事情就是不使用 时间戳 但是 日期时间 对于必须包含日期不在1970和2038之间的列。

    不过有一个小提示:可能有一个非常高的风险 (从统计上讲) 您的应用程序在2038年之前会被重新编写好几次^^^^^因此,如果您不必在将来处理日期,您就不必在当前版本的应用程序中处理该问题。。。

        3
  •  7
  •   Rubens Farias    16 年前

    Year 2038 problem

    1. 2038年的问题(也被称为Unix千年虫,与Y2K问题类似的Y2K38)可能会导致某些计算机软件在2038年之前或之后出现故障
    2. 此问题影响所有将系统时间存储为有符号32位整数的软件和系统,并将此数字解释为自1970年1月1日UTC 00:00:00以来的秒数。以这种方式表示的最新时间是周二UTC 03:14:07,2038年1月19日。超过这一时刻的时间将“环绕”,并在内部存储为负数,这些系统将其解释为1901年的日期,而不是2038年的日期
        4
  •  2
  •   Addsy    16 年前

    http://en.wikipedia.org/wiki/Year_2038_problem 有大部分的细节

    总之:

    对于只存储过去日期的系统,我想您暂时不必担心!主要的问题是那些在将来使用日期的系统。如果你的系统需要在未来28年内运行,那么你现在就应该开始担心了!

    4) 见3!

    5) 参见第4章!!!;)

        5
  •  1
  •   Dexter    15 年前

    Bros,如果您需要使用PHP显示时间戳,这是最好的PHP解决方案,无需更改UNIX_时间戳格式。

    Here's the DateTime solution .

    只要在数据库中有未签名的BIGINT(8)作为时间戳。 只要你有PHP5.2.0++

        6
  •  -1
  •   Venkatesh GS Rao    10 年前

    $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'];
    

    这可能不是一个有效的方法,但它是有效的。