Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange behavior with the strtotime function passing a wrong date and time format

Tags:

php

strtotime

I'm trying to understand the following behavior of the date function strtotime():

  • strtotime(1420066800) returns false, as expected.
  • strtotime(1451602800) returns 26197048320! But expected false as 1451602800 is not a valid date and time format. (same thing with new DateTime(1451602800) as well)

I read the whole Supported Date and Time Formats page, but didn't find any match for this input.

By the way, these are timestamps of 2015-01-01 and 2016-01-01 relatively.

Any insights will be appreciated.

Update:
Different versions test results:

PHP 5.1.6  => false
PHP 5.2.17 => 26197048320
PHP 5.3.29 => 26197048320
PHP 5.4.34 => 26197048320
PHP 5.5.18 => 26197048320
PHP 5.6.2  => 26197048320
PHP 5.6.17 => 26197048320
PHP 7.0.2  => 26197048320

Running on Mac OS X 10.11.3

like image 628
Slavik Meltser Avatar asked Feb 25 '16 16:02

Slavik Meltser


1 Answers

Let's start with the right way to do it. If you want to pass a timestamp to strtotime you have to prefix it with '@'. It is explained on the Compound Formats page, under "Localized notations" -> "Unix Timestamp".

echo(date('r', strtotime('@1420066800'))."\n");
echo(date('r', strtotime('@1451602800'))."\n");

The output is:

Thu, 01 Jan 2015 01:00:00 +0200
Fri, 01 Jan 2016 01:00:00 +0200

Now, why strtotime() returns false for 1420066800 and 26197048320 for 1451602800?

It expects to receive a string and if it receives a number it doesn't care and converts it to string first. Then it follows some rules and tries to identify the date components into the string. Because neither '1420066800' nor '1451602800' contains any separator for components, it probably tries to guess the order of components.

Today, 2016-02-25, strtotime('1451602800') produces a timestamp that, converted to a printable date looks like: 'Fri, 25 Feb 2800 14:52:00 +0200'

It makes me think it interprets the input string as follows: 14:51:60 is the time, 2800 is the year, the other components (day, month) are initialized from the current time.

The documentation says:

The function expects to be given a string containing an English date format and will try to parse that format into a Unix timestamp (the number of seconds since January 1 1970 00:00:00 UTC), relative to the timestamp given in $now, or the current time if $now is not supplied.

Since the "date" you provide doesn't follow any valid date-time format, strtotime() is free to return any value. It is called "garbage in, garbage out".

like image 79
axiac Avatar answered Sep 21 '22 01:09

axiac