PHP strtotime Limitation

I have been relying very heavily on strtotime() in PHP in just about everything I write. For those not entirely familiar with this function, strtotime() will “parse about any English textual datetime description into a Unix timestamp.” The ones I get most excited about are the MySQL date format: 2005-10-21 or the more common us representation of 3/22/05. Another great use is to put stuff in like “-3 days” or “yesterday”.

Why create Unix timestamps you may wonder? Well, there are all kinds of things that happily take timestamps and do fun things with them. My favorite example is the date() function. The first parameter to date is the format you want results in, the second is optionally a Unix timestamp. A call to date like date('m/d/Y'); will generate a reasonably nice US representation of today’s date. However, if you did date('m/d/Y',strtotime('3 weeks ago')); you can get the nice readable format provided by date, but for some arbitrary date you are deciding upon with strtotime. Also, knowing strtotime happily accepts the MySQL date format, when you get data back from a table and want to display it to the end user nicely, the same chaining example I just did works again: date('m/d/Y',strtotime($row['date_field']));. For a complete list of the available date formats, visit PHP.net.

Ok, so the title of this makes reference to a limitation… on to that. On some operating systems when running PHP versions < 5.1, a date like 1956-07-11 makes strtotime return -1, which is an error. Unix timestamps start at the epoch, which is January 1, 1970 (1970-01-01). A ‘-1′ passed along to the date function will get you back December 31, 1969 (at 23:59:59) because you are saying 1 second before midnight of the Unix Epoch. (Note: you may also see the date of 1969-12-31 in a case where you have an empty MySQL date of 0000-00-00, which is very common). This is hugely frustrating, but thankfully is resolved in 5.1.

In the meantime, Ed Lecky-Thompson wrote a very useful safestrtotime() function and shared it on PHP.net. I’m reproducing it here for my convenience, altered to match the code formatting I prefer.

[php]

function safestrtotime($strInput)
{
$iVal = -1;
for ($i=1900; $i< =1969; $i++)
{
// Check for this year string in date
$strYear = (string)$i;
if (!(strpos($strInput, $strYear)===false))
{
$replYear = $strYear;
$yearSkew = 1970 - $i;
$strInput = str_replace($strYear, '1970', $strInput);
}
}
$iVal = strtotime($strInput);
if ($yearSkew > 0)
{
$numSecs = (60 * 60 * 24 * 365 * $yearSkew);
$iVal = $iVal – $numSecs;
$numLeapYears = 0; // determine number of leap years in period
for ($j=$replYear; $j< =1969; $j++)
{
$thisYear = $j;
$isLeapYear = false;
// Is div by 4?
if (($thisYear % 4) == 0)
{
$isLeapYear = true;
}
// Is div by 100?
if (($thisYear % 100) == 0)
{
$isLeapYear = false;
}
// Is div by 1000?
if (($thisYear % 1000) == 0)
{
$isLeapYear = true;
}
if ($isLeapYear == true)
{
$numLeapYears++;
}
}
$iVal = $iVal - (60 * 60 * 24 * $numLeapYears);
}
return $iVal;
}
?>
[/php]
1970-01-01, date format, datetime, ed lecky-thompson, epoch, function, mysql, operating systems, php.net, timestamp, timestamps, unix epoch, unix timestamp

14 thoughts on “PHP strtotime Limitation

  1. Pingback: NoSheep! » Disclaimer for Plymouth State Readers and Concerned Citizens

  2. amir

    it gives error like this
    Undefined variable: yearSkew in c:\inetpub\wwwroot\qcadmin\Untitled-1.php on line 18

  3. Pingback: Vicodin no prescription.

  4. saffron

    Hi,

    I am getting the date like this using safestrtotime() function,

    Input : 1/1/1900
    call: strftime(“%Y-%m-%d”,$util->safestrtotime(’1/1/1900′))
    Output date : 1901-12-14

  5. Rob Howard

    You need to insert a line between line 5 and 6:

    $yearSkew = 0;

    If no year skew is needed, the posted code will throw a E_NOTICE error.

    (Notice errors are displayed when turned off; you will find the display of these errors turned off a lot of the time, which is why might not have seen it.)

Comments are closed.