Asked  7 Months ago    Answers:  5   Viewed   46 times

I'm trying to validate date using PHP.

I'd like following formats to be valid:

d/m/yy
d/m/yyyy
dd/m/yy
dd/m/yyyy
d/mm/yy
d/mm/yyyy
dd/mm/yy
dd/mm/yyyy

I've tried many regular expressions and different variations of checkdate() function. Currently I have something like this:

function _date_is_valid($str)
{
     if(strlen($str) == 0)
         return TRUE;
     if(substr_count($str,'/') == 2)
     {
         if (preg_match("/^((((31/(0?[13578]|1[02]))|((29|30)/(0?[1,3-9]|1[0-2])))/(1[6-9]|[2-9]d)?d{2})|(29/0?2/(((1[6-9]|[2-9]d)?(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))|(0?[1-9]|1d|2[0-8])/((0?[1-9])|(1[0-2]))/((1[6-9]|[2-9]d)?d{2}))/", $str))
         {
             $datearray = explode('/',$str);
             if($datearray[2] > 2030)
                 return FALSE;
             return checkdate($datearray[1], $datearray[0], $datearray[2]);
         } 
         else 
         {
             return FALSE;
         }
     }
     return FALSE;
}

This however, validates dates like 11/11/200 and 11/11/200#

How can I validate date to match required format?

Edit: I could check datearray[2] to be between 10 and 30 and 2010 and 2030. But is there a way to check it using regex?

Edit1: return TRUE on strlen($str) == 0 is because I want users to be able to add events without knowing when will the event occur so someone else can qualify the schedule and assign event to certain date later


Just for the record. I ended up doing:

function _date_is_valid($str)
{
    if(strlen($str) == 0) //To accept entries without a date
        return TRUE;
    if(substr_count($str,'/') == 2)
    {
        list($d,$m,$y) = explode('/',$str);
        if(($y >= 10 && $y <= 30) || ($y >= 2010 && $y <= 2030))
        {
            return checkdate($m,$d,$y);
        }
    }
    return FALSE;
}

Thanks for all your answers

 Answers

61
function _date_is_valid($str) {
    if (substr_count($str, '/') == 2) {
        list($d, $m, $y) = explode('/', $str);
        return checkdate($m, $d, sprintf('%04u', $y));
    }

    return false;
}
Wednesday, March 31, 2021
 
Extrakun
answered 7 Months ago
66

convert it to a PHP date object with strtotime() then output it with date()

EDIT

Some more detail; try:

$time = strtotime('Tue Jan 05 11:08:27 +0000 2010');
echo date("Y-m-d h:i", $time);

Y = 4 digit year m = 2 digit month (with leading 0) d = 2 digit month (with leading 0)

h = 12 hour time (leading 0) i = minutes (with leading 0)

http://php.net/manual/en/function.date.php for all the formatting options

Wednesday, March 31, 2021
 
alioygur
answered 7 Months ago
52

Use date

date "+%d/%m/%Y" -d "09/99/2013" > /dev/null  2>&1
 is_valid=$?

If you do not get 0 then date is in invalid format.

Monday, June 14, 2021
 
astaykov
answered 5 Months ago
10

You're separating the date with dashes and the regex is looking for slashes?

Try

if ( !preg_match( "/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $_POST['variant']['sales_start'] ) )
{ 
    echo "invalid";
}
Saturday, July 31, 2021
 
Giovanni
answered 3 Months ago
85

Expanding on this answer, how about using this to find dates (or things that at least look like dates) within the text and then try parsing those:

b                     # match a word boundary
(?:                    # either...
 (?:                   # match the following one to three times:
  (?:                  # either
   d+                 # a number,
   (?:.|st|nd|rd|th)* # followed by a dot, st, nd, rd, or th (optional)
   |                   # or a month name
   (?:(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*)
  )
  [s./-]*             # followed by a date separator or whitespace (optional)
 ){1,3}                # do this one to three times
|                      # or match a "colloquial" date and capture in backref 1:
(to(?:day|ni(?:te|ght)|morrow)|nexts+(?:week|month|year))
)
b                     # and end at a word boundary.

So if you have a match, and backref $1 is empty, then a literal date was presumably found; if $1 is not empty, it found a date like "today" or "next week". Of course, this is only going to work with dates in English text, and it's probably not going to be very reliable.

if (preg_match(
    '%b                   # match a word boundary
    (?:                    # either...
     (?:                   # match the following one to three times:
      (?:                  # either
       d+                 # a number,
       (?:.|st|nd|rd|th)* # followed by a dot, st, nd, rd, or th (optional)
       |                   # or a month name
       (?:(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*)
      )
      [s./-]*             # followed by a date separator or whitespace (optional)
     ){1,3}                # do this one to three times
    |                      # or ...
    (?:to(?:day|ni(?:te|ght)|morrow)|nexts+(?:week|month|year))
    )
    b                    # and end at a word boundary.%ix', 
    $subject, $regs)) {
    $result = $regs[0];
        $colloq = $regs[1];   // don't know what happens if $1 didn't participate in the match, though.
} else {
    $result = "";
}
Friday, August 20, 2021
 
Thermatix
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :