Pregunta

I am having an interesting problem with the mktime function. I looked at the solutions offered on here prior and none seemed to be resolved or helped (strotime doesn't change the results I see).

I have a monthly report that I am trying to make as error-proof as possible for my users, so I'm only requesting a month and a year. I will provide the best day for the report in the code.

My form has a drop-down selection for the months, and the values for the month are two-digit integers (01, 02, etc). The year is four-digit, filled out manually by the user.

Every works great up until the year 2038... I know, I know, it's a long way off, but the project is supposed to have a 20-year scope and so in the last two years, I'm running into issues.

here's how I'm receiving the information from the form:

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

Then, I use mktime to combine the month and year with my day (27th): $timeStamp = mktime(0,0,0,$month,27,$year);

Then I assign it to a variable in a date form that MySQL likes: $reportdate = date('Y-m-j',$timeStamp);

I've echoed out the results of $month and $year and they are coming across correctly, but when I echo out $reportdate, it always says 12/31/1969.

03
2038
1969-12-31

It doesn't matter what month I choose. December 2037 reports perfectly, anything beyond that fails.

Is this something that is fixable or am I just going to have to say that's the way the cookie crumbles...?

¿Fue útil?

Solución

This is because your timestamp is overflowing, and is caused by the year 2038 problem.

Basically, integers are represented as signed 32-bits numbers, which can hold a maximum value of 2147483648. So, in a UNIX timestamp, that is a certain amount in seconds, which is about 68 years.

In fact, Google tells me:

(2^31) * seconds = 68.0511039 years

So, UNIX timestamp is time since the UNIX epoch, Jan 1st 1970 00:00:00 UTC, meaning the largest date that can be represented in a 32-bit UNIX timestamp would have a year of:

1970 + ~68 = ~2038.

If you need to support these dates, use the DateTime class, as it does not have such a restriction, like so:

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

Otros consejos

As explained above, you're hitting the 2038 problem with mktime.

Luckily, it is fixable: don't use mktime. Just build your $reportdate value another way, that doesn't use mktime. Such as:

 $reportdate = $year."-".$month."-27";
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top