tags:

views:

49

answers:

2

I have a function that takes a string date in the format 08/24/2010 and turns it into a timestamp. The problem I have is that dates such as 08/24/2090 are converted improperly.

Here is my function:

/**
* Converts a date to a timestamp
* for a date formatted such as: 08/24/2010 12:00:00, 08-24-2010 12:00:00 or 08/24/2010
* 
* @param string date
* @return string
*/
public static function dateToTimeStamp($date)
{
    if (!strstr($date, ' ')) $date .= ' ' . date('h:i:s');
    list($date, $time) = explode(' ', $date);
    list($month, $day, $year) = (strstr($date, '/') ? explode('/', $date) : explode('-', $date));
    list($hour, $minute, $second) = explode(':', $time);

    $timestamp = mktime($hour, $minute, $second, $month, $day, $year);
    return date('Y-m-d h:i:s', $timestamp);
} 

I just passed in 09/30/2090 and I get back 1969-12-31 04:00:00 but when I pass in 09/30/2020, I get back 2020-09-30 08:54:44.

+2  A: 

strtotime and mktime suffer from the Y2038 bug. Unix timestamps count the number of seconds since January 1, 1970, and if it uses a 32-bit integer, that interger will overflow on January 19, 2038, which will cause PHP to not know how to parse the date.

The valid range of a timestamp is typically from Fri, 13 Dec 1901 20:45:54 UTC to Tue, 19 Jan 2038 03:14:07 UTC. (These are the dates that correspond to the minimum and maximum values for a 32-bit signed integer.) Additionally, not all platforms support negative timestamps, therefore your date range may be limited to no earlier than the Unix epoch. This means that e.g. dates prior to Jan 1, 1970 will not work on Windows, some Linux distributions, and a few other operating systems. PHP 5.1.0 and newer versions overcome this limitation though.

Despite what that warning in the manual says though, versions of PHP after 5.1 still are affected by the 2038 bug when using mktime and strtotime. The DateTime class overcomes this bug, however, and should be used instead.

public static function dateToTimeStamp($date)
{
  if (!strstr($date, ' ')) $date .= ' ' . date('h:i:s');
  $d = new DateTime($date);
  return $d->format('Y-m-d h:i:s');
}

Note that DateTime was added in PHP 5.2.

Daniel Vandersluis
Even post PHP 5.1.0, PHP still uses a 32-bit timestamp on a 32-bit platform, so simply upgrading won't resolve the problem.
Mark Baker
@Mark yeah I know, I've updated my answer to address that.
Daniel Vandersluis
+1 for the additional example of datetime objects
Mark Baker
+2  A: 

If you need dates that fall outside the 32-bit range of a Unix timestamp, you should start using the PHP datetime object which gives you a daterange that predates the big bang, and will probably even outlive the burn-out of the sun

Mark Baker