Check if variable is a valid date with PHP

2020-01-30 23:51发布

问题:

I am working on a script that will import some data from a CSV file. As I am doing this I want to be able to check a variable to see if it is a valid date string.

I have seen several ways to check if a sting is a date, but most of them require you to now the format. I will not know the format that the date will in.

right now I am using strtotime(), but this fails to easily

$field ="May";
if(strtotime($field)){
    echo "This is a date";
}

In this case, "May" was the persons first name, and not a date at all.

Can any one recommend more reliable function?

Edit based on questions from some of you.

For a variable to pass as a "date" in my case, it would need to be specific to a day/month/year, so just "May" would be to vague to count.

Based on that and Pauls good point below we can also test to see if the string contains a number, such as

$field ="May";
if(strtotime($field) && 1 === preg_match('~[0-9]~', $field)){
    echo "This is a date";
}else{
    echo "Nope not a date";
}

This seems to cover my immediate needs, but can any one spot any issues or suggest improvements?

回答1:

Use date_parse and check the values of the returned array

$date = date_parse("May")

// ["year"] == FALSE
// ["month"] == 5
// ["day"] == FALSE

You can also pass those into checkdate.

$date = date_parse($someString);
if ($date["error_count"] == 0 && checkdate($date["month"], $date["day"], $date["year"]))
    echo "Valid date";
else
    echo "Invalid date";


回答2:

I don't think there is a all-in-one answer to this problem. You may have different strategy depending on your use case.

Your strtotime() is a perfect solution, but as you say, you may end up with false positive. Why? Because may may be a word or a name. However, what is the result of strtotime('May')?

echo date(DateTime::ISO8601, strtotime('May'));
2012-05-21T00:00:00+0200

So giving only the month will return a date of the current year and the current day starting at midnight with the given month. A possible solution would be to check if your string has the current day and/or the current year included, this way, you may check against to make sure your date is a fully qualified date and valid.

echo date(DateTime::ISO8601, strtotime('May Day')); // (strtotime() returns false)
1970-01-01T01:00:00+0100

echo date(DateTime::ISO8601, strtotime('May 21'));
2012-05-21T00:00:00+0200

A simple strpos() or even a regex should do the trick.

However it is a bit odd and should be used only if you have no other way to do.

I believe that a better solution would be to define a set of valid format and interpolate the result to make sure that the date is valid.

$validDateFormatPatterns = array(
 '[0-9]{1,2}-[0-9]{1,2}-[0-9]{4}', // 21-05-2012, obviously this pattern is simple and would accept 05-21-2012,
 'the [0-9]{1,2}(th|st|nd|rd) (January|February|...|May|...|December) [0,9]{4}', // The 21st May 2012
);

You should try to cover most of the case and I'm sure you will be able to find regex that checks for most current date format.

In any case, you may need to adapt your function from time to time because there is no easy way to make it bulletproof.



回答3:

I know this was asked a long time ago, but looking around for this and trying to avoid regex, I came up with this:

function checkInputIsDate($date) {
    return (bool)strpbrk($date,1234567890) && strtotime($date);
}

This works because it takes away the issues posted above where only a month is passed into strtotime by making sure there are numbers in the string with strpbrk as well as verifying strtotime outputs a date.

And learned about a function I didn't know existed.

Hope this helps someone.