【问题标题】:mktime forcing date to December 1969mktime 强制日期到 1969 年 12 月
【发布时间】:2012-07-02 20:01:36
【问题描述】:

我在使用 mktime 函数时遇到了一个有趣的问题。我之前查看了此处提供的解决方案,但似乎都没有得到解决或帮助(strotime 不会改变我看到的结果)。

我有一份月度报告,我正在努力为我的用户制作尽可能不出错的报告,所以我只要求一个月和一年。我将在代码中提供报告的最佳日期。

我的表单有一个月份的下拉选项,月份的值是两位整数(01、02 等)。年份为四位数字,由用户手动填写。

在 2038 年之前,一切都很好...我知道,我知道,这还有很长的路要走,但这个项目应该有 20 年的范围,所以在过去的两年里,我正在运行进入问题。

这是我从表单中接收信息的方式:

$month = filter_var($_POST["month"], FILTER_SANITIZE_NUMBER_INT);
$year = filter_var($_POST["year"], FILTER_SANITIZE_NUMBER_INT);

然后,我使用 mktime 将月份和年份与我的日期(27 日)结合起来: $timeStamp = mktime(0,0,0,$month,27,$year);

然后我将它分配给 MySQL 喜欢的日期形式的变量: $reportdate = date('Y-m-j',$timeStamp);

我已经回显了 $month 和 $year 的结果,它们的显示是正确的,但是当我回显 $reportdate 时,它​​总是显示 12/31/1969。

03
2038
1969-12-31

我选择哪个月份并不重要。 2037 年 12 月的报告完美无缺,除此之外的任何事情都失败了。

这是可以修复的,还是我只能说这就是 cookie 崩溃的方式...?

【问题讨论】:

    标签: php date mktime


    【解决方案1】:

    这是因为你的时间戳溢出了,是year 2038 problem引起的。

    基本上,整数表示为带符号的 32 位数字,其最大值可以为 2147483648。因此,在 UNIX 时间戳中,这是以秒为单位的一定数量,大约是 68 年。

    事实上,谷歌告诉我:

    (2^31) * seconds = 68.0511039 years
    

    因此,UNIX 时间戳是自 UNIX 纪元 1970 年 1 月 1 日 00:00:00 UTC 以来的时间,这意味着可以在 32 位 UNIX 时间戳中表示的最大日期为:

    1970 + ~68 = ~2038.
    

    如果您需要支持这些日期,请使用DateTime 类,因为它没有这样的限制,如下所示:

    $date = new DateTime( "now", new DateTimeZone( 'America/New_York'));
    $date->setDate( $year, $month, 27);
    // $date->setTime( 0, 0, 0);
    echo $date->format('Y-m-j');
    

    【讨论】:

    • 是的。使用无符号整数而不是有符号整数。
    • PHP 中没有这样的功能,因为整数在内部表示为有符号的。
    • @Dancrumb - 没错,虽然这不是解释,但更多的是注释。
    • @nickb: 完全同意 - 遗憾的是 PHP 文档课程的标准杆
    【解决方案2】:

    如上所述,您遇到了 mktime 的 2038 问题。

    幸运的是,它是可以修复的:不要使用 mktime。只需以另一种方式构建您的$reportdate 值,即不使用mktime。如:

     $reportdate = $year."-".$month."-27";
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-17
      • 2018-04-11
      • 1970-01-01
      • 2011-01-24
      • 1970-01-01
      • 2021-07-13
      相关资源
      最近更新 更多