1

我对 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('Ymj',$timeStamp);

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

03
2038
1969-12-31

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

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

4

2 回答 2

4

这是因为您的时间戳溢出,并且是由2038 年问题引起的。

基本上,整数表示为带符号的 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');
于 2012-07-02T20:03:17.853 回答
0

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

幸运的是,它是可以修复的:不要使用 mktime。只是$reportdate以另一种方式建立你的价值,不使用mktime. 如:

 $reportdate = $year."-".$month."-27";
于 2012-07-02T20:12:15.623 回答