php check for a valid date, weird date conversions

25,767

Solution 1

From php.net

<?php
function isValidDateTime($dateTime)
{
    if (preg_match("/^(\d{4})-(\d{2})-(\d{2}) ([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/", $dateTime, $matches)) {
        if (checkdate($matches[2], $matches[3], $matches[1])) {
            return true;
        }
    }

    return false;
}
?>

Solution 2

As mentioned here: https://bugs.php.net/bug.php?id=45647

There is no bug here, 00-00-00 means 2000-00-00, which is 1999-12-00, which is 1999-11-30. No bug, perfectly normal.

And as shown with a few tests, rolling backwards is expected behavior, if a little unsettling:

>> date('Y-m-d', strtotime('2012-03-00'))
string: '2012-02-29'
>> date('Y-m-d', strtotime('2012-02-00'))
string: '2012-01-31'
>> date('Y-m-d', strtotime('2012-01-00'))
string: '2011-12-31'
>> date('Y-m-d', strtotime('2012-00-00'))
string: '2011-11-30'

Solution 3

echo date('Y-m-d', strtotime($date));

results in: "1999-11-30"

The result of strtotime is 943920000 - this is the number of seconds, roughly, between the Unix epoch (base from which time is measured) to 1999-11-30.

There is a documented mysql bug on mktime(), localtime(), strtotime() all returning this odd value when you try a pre-epoch time (including "0000-00-00 00:00:00"). There's some debate on the linked thread as to whether this is actually a bug:

Since the time stamp is started from 1970, I don't think it supposed to work in anyways.

Below is a function that I use for converting dateTimes such as the above to a timestamp for comparisons, etc, which may be of some use to you, for dates beyond "0000-00-00 00:00:00"

/**
 * Converts strings of the format "YYYY-MM-DD HH:MM:SS" into php dates
 */
function convert_date_string($date_string)
{
    list($date, $time) = explode(" ", $date_string);
    list($hours, $minutes, $seconds) = explode(":", $time);
    list($year, $month, $day) = explode("-", $date);
    return mktime($hours, $minutes, $seconds, $month, $day, $year);
}

Solution 4

If you just want to handle a date conversion without the time for a mysql date field, you can modify this great code as I did. On my version of PHP without performing this function I get "0000-00-00" every time. Annoying.

function ConvertDateString ($DateString)
{
    list($year, $month, $day) = explode("-", $DateString);
    return date ("Y-m-d, mktime (0, 0, 0, $month, $day, $year));
}

Solution 5

This version allows for the field to be empty, has dates in mm/dd/yy or mm/dd/yyyy format, allow for single digit hours, adds optional am/pm, and corrects some subtle flaws in the time match.

Still allows some pathological times like '23:14 AM'.

function isValidDateTime($dateTime) {
    if (trim($dateTime) == '') {
        return true;
    }
    if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{2,4})(\s+(([01]?[0-9])|(2[0-3]))(:[0-5][0-9]){0,2}(\s+(am|pm))?)?$/i', $dateTime, $matches)) {
        list($all,$mm,$dd,$year) = $matches;
        if ($year <= 99) {
            $year += 2000;
        }
        return checkdate($mm, $dd, $year);
    }
    return false;
}
Share:
25,767
SeanDowney
Author by

SeanDowney

I'm a nerd!

Updated on June 05, 2020

Comments

  • SeanDowney
    SeanDowney almost 4 years

    Is there a way to check to see if a date/time is valid you would think these would be easy to check:

    $date = '0000-00-00';
    $time = '00:00:00';
    $dateTime = $date . ' ' . $time;
    
    if(strtotime($dateTime)) {
        // why is this valid?
    }
    

    what really gets me is this:

    echo date('Y-m-d', strtotime($date)); 
    

    results in: "1999-11-30",

    huh? i went from 0000-00-00 to 1999-11-30 ???

    I know i could do comparison to see if the date is either of those values is equal to the date i have but it isn't a very robust way to check. Is there a good way to check to see if i have a valid date? Anyone have a good function to check this?

    Edit: People are asking what i'm running: Running PHP 5.2.5 (cli) (built: Jul 23 2008 11:32:27) on Linux localhost 2.6.18-53.1.14.el5 #1 SMP Wed Mar 5 11:36:49 EST 2008 i686 i686 i386 GNU/Linux

  • SeanDowney
    SeanDowney over 15 years
    i tried date('Y-m-d', convert_date_string('0000-00-00 00:00:00')) but still gives the 1999 date
  • ConroyP
    ConroyP over 15 years
    Found the PHP bug report on the odd behaviour of time-based functions in PHP for the 0000-00.. value. There is some debate on that thread as to whether it's actually a bug, as if people would ever want to calculate a date pre-1970!
  • Ville Salonen
    Ville Salonen over 12 years
    This doesn't work with some edge cases such as February 31st or April 31st. For example date("Y-m-d", strtotime("31.2.2012")) results in "2012-03-02" which passes the checkdate validation even though user didn't input a valid date.
  • SeanDowney
    SeanDowney about 12 years
    that would work for dates that are "recent", but if I have a date in the early ninety's it would always return false
  • Josue
    Josue about 11 years
    @SeanDowney edited, which should return TRUE for your "date in the early ninety's".