mktime强制日期到1969年12月


mktime forcing date to December 1969

我在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 = 日期('Y-m-j',$timeStamp);

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

03
2038
1969-12-31

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

这是可以修复的,还是我不得不说这就是饼干碎裂的方式......?

这是因为您的时间戳溢出,并且是由 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');

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

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

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