正确确定日期字符串是否为该格式的有效日期

Mar*_*ace 170 php datetime date

我从API接收日期字符串,格式为yyyy-mm-dd.

我目前正在使用正则表达式验证字符串格式,这可以正常工作,但我可以看到一些情况,根据字符串,它可能是一个正确的格式,但实际上是一个无效的日期.即2013-13-01,例如.

有没有更好的方法在PHP中获取字符串,2013-13-01并告诉它是否是格式的有效日期yyyy-mm-dd

Ama*_*ali 418

您可以使用DateTime类来实现此目的:

function validateDate($date, $format = 'Y-m-d')
{
    $d = DateTime::createFromFormat($format, $date);
    // The Y ( 4 digits year ) returns TRUE for any integer with any number of digits so changing the comparison from == to === fixes the issue.
    return $d && $d->format($format) === $date;
}
Run Code Online (Sandbox Code Playgroud)

[ 功能取自这个答案.也在php.net上.最初由格拉维奇撰写.]


测试用例:

var_dump(validateDate('2013-13-01'));  // false
var_dump(validateDate('20132-13-01')); // false
var_dump(validateDate('2013-11-32'));  // false
var_dump(validateDate('2012-2-25'));   // false
var_dump(validateDate('2013-12-01'));  // true
var_dump(validateDate('1970-12-01'));  // true
var_dump(validateDate('2012-02-29'));  // true
var_dump(validateDate('2012', 'Y'));   // true
var_dump(validateDate('12012', 'Y'));  // false
Run Code Online (Sandbox Code Playgroud)

演示!

  • 如果您使用的是PHP 5.2.x,则应使用`strtotime`获取unix时间戳,然后使用`date('Ym -d',$ t)`来获取字符串日期.然后你就像这个答案一样比较它们. (13认同)
  • 该功能正常工作.它返回false,因为您指定的thr格式不正确.如果你想使用没有前导零的日期和月份,那么格式应该是''Yn-j'`,@ reignly. (4认同)
  • @pedromanoel:对于标准日期时间输入,您可以使用`strtotime`,但对于`strtotime`无法识别的非标准格式,您将需要一些其他解决方案.对于php版本5.2支持在2011年1月停止,因为5.3支持在2014年8月停止. (2认同)
  • 考虑这个日期`var_dump(validateDate('2012-2-9'));` (2认同)

小智 73

确定是否有任何字符串是日期

function checkIsAValidDate($myDateString){
    return (bool)strtotime($myDateString);
}
Run Code Online (Sandbox Code Playgroud)

  • @MichelAyres这是因为php认为`2015-02-30`是一个有效的日期,因为当给定的日期大于给定月份的天数(或负数)时,php将滚动到下个月.由于日期保证格式为`yyyy-mm-dd`,可以通过将返回值更改为`return(bool)strtotime($ myDateString)&& date("Ymd",strtotime($ myDateString))来修复= $ myDateString;`. (9认同)
  • 这验证了整个范围的有效日期格式,而不仅仅是 `yyyy-mm-dd`。 (2认同)
  • 为什么`(bool)strtotime('s')`是真实的? (2认同)

vin*_*eet 32

使用php预建函数以简单的方式使用:

function checkmydate($date) {
  $tempDate = explode('-', $date);
  // checkdate(month, day, year)
  return checkdate($tempDate[1], $tempDate[2], $tempDate[0]);
}
Run Code Online (Sandbox Code Playgroud)

测试

   checkmydate('2015-12-01'); //true
   checkmydate('2015-14-04'); //false
Run Code Online (Sandbox Code Playgroud)

  • 这假设$ tempDate数组中至少有3个元素. (4认同)
  • @ person27:`return sizeof($ tmpDate)== 3 && checkdate($ tmpDate [1] ...` (2认同)

mig*_*gli 14

确定字符串是否为日期,即使字符串是非标准格式

(strtotime不接受任何自定义格式)

<?php
function validateDateTime($dateStr, $format)
{
    date_default_timezone_set('UTC');
    $date = DateTime::createFromFormat($format, $dateStr);
    return $date && ($date->format($format) === $dateStr);
}

// These return true
validateDateTime('2001-03-10 17:16:18', 'Y-m-d H:i:s');
validateDateTime('2001-03-10', 'Y-m-d');
validateDateTime('2001', 'Y');
validateDateTime('Mon', 'D');
validateDateTime('March 10, 2001, 5:16 pm', 'F j, Y, g:i a');
validateDateTime('March 10, 2001, 5:16 pm', 'F j, Y, g:i a');
validateDateTime('03.10.01', 'm.d.y');
validateDateTime('10, 3, 2001', 'j, n, Y');
validateDateTime('20010310', 'Ymd');
validateDateTime('05-16-18, 10-03-01', 'h-i-s, j-m-y');
validateDateTime('Monday 8th of August 2005 03:12:46 PM', 'l jS \of F Y h:i:s A');
validateDateTime('Wed, 25 Sep 2013 15:28:57', 'D, d M Y H:i:s');
validateDateTime('17:03:18 is the time', 'H:m:s \i\s \t\h\e \t\i\m\e');
validateDateTime('17:16:18', 'H:i:s');

// These return false
validateDateTime('2001-03-10 17:16:18', 'Y-m-D H:i:s');
validateDateTime('2001', 'm');
validateDateTime('Mon', 'D-m-y');
validateDateTime('Mon', 'D-m-y');
validateDateTime('2001-13-04', 'Y-m-d');
Run Code Online (Sandbox Code Playgroud)


gal*_*lki 12

这个选项不仅简单,而且几乎可以接受任何格式,但是对于非标准格式,它可能是错误的.

$timestamp = strtotime($date);
return $timestamp ? $date : null;
Run Code Online (Sandbox Code Playgroud)

  • @rolinger,对于相同的结果,它更慢并且代码更多。“202-03-31”是 3 世纪的真实日期,我不明白为什么你声称它不是有效日期。 (3认同)
  • 重要的是要注意,这将不适用于英国(d / m / Y)格式,因为它将假定它正在转换美国(m / d / Y)。仅当一天少于12天时,它才似乎起作用! (2认同)

Suv*_*ker 9

您还可以解析月份日期和年份的日期,然后您可以使用PHP函数checkdate(),您可以在这里阅读:http://php.net/manual/en/function.checkdate.php

你也可以尝试这个:

$date="2013-13-01";

if (preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/",$date))
    {
        echo 'Date is valid';
    }else{
        echo 'Date is invalid';
    }
Run Code Online (Sandbox Code Playgroud)

  • 此解决方案非常差,因为它无法在任何意义上检查日期有效性.任何一个月都可以有31天,包括2月.任何一年都可以有2月29日.要使用RegExp验证日期,需要更复杂的东西,背面引用和负面预测. (4认同)

Bar*_*ajz 8

恐怕大多数投票的解决方案(/sf/answers/1349000411/)无法正常工作。第四个测试用例 (var_dump(validateDate('2012-2-25')); // false) 是错误的。日期是正确的,因为它对应于格式 - m允许带或不带前导零的月份(请参阅:http : //php.net/manual/en/datetime.createfromformat.php)。因此,日期2012-2-25的格式为Ymd,并且测试用例必须为真而非假。

我相信更好的解决方案是测试可能的错误如下:

function validateDate($date, $format = 'Y-m-d') {
    DateTime::createFromFormat($format, $date);
    $errors = DateTime::getLastErrors();

    return $errors['warning_count'] === 0 && $errors['error_count'] === 0;
}
Run Code Online (Sandbox Code Playgroud)


小智 7

符合cl-sah的答案,但这听起来更好,更短......

function checkmydate($date) {
  $tempDate = explode('-', $date);
  return checkdate($tempDate[1], $tempDate[2], $tempDate[0]);
}
Run Code Online (Sandbox Code Playgroud)

测试

checkmydate('2015-12-01');//true
checkmydate('2015-14-04');//false
Run Code Online (Sandbox Code Playgroud)


Vic*_*der 6

我有这个东西,即使使用PHP,我也希望找到功能性解决方案.所以,例如,@ migli给出的答案确实很好,非常灵活和优雅.

但它有一个问题:如果你需要用相同的格式验证很多DateTime字符串怎么办?你必须在整个地方重复这种格式,这与DRY原则背道而驰.我们可以将格式放在常量中,但是,我们必须将常量作为参数传递给每个函数调用.

但不要再害怕了!我们可以使用currying来救援!PHP不会使这个任务变得愉快,但仍然可以用PHP实现currying:

<?php
function validateDateTime($format)
{
    return function($dateStr) use ($format) {
        $date = DateTime::createFromFormat($format, $dateStr);
        return $date && $date->format($format) === $dateStr;
    };
}
Run Code Online (Sandbox Code Playgroud)

那么,我们刚刚做了什么?基本上我们将函数体包装成匿名并返回这样的函数.我们可以像这样调用验证函数:

validateDateTime('Y-m-d H:i:s')('2017-02-06 17:07:11'); // true
Run Code Online (Sandbox Code Playgroud)

是的,没有太大的区别......但真正的力量来自部分应用的功能,通过currying来实现:

// Get a partially applied function
$validate = validateDateTime('Y-m-d H:i:s');

// Now you can use it everywhere, without repeating the format!
$validate('2017-02-06 17:09:31'); // true
$validate('1999-03-31 07:07:07'); // true
$validate('13-2-4 3:2:45'); // false
Run Code Online (Sandbox Code Playgroud)

功能编程FTW!

  • 滑坡的最佳答案恕我直言(以更大的灵活性解决了 OP 的特定问题,并且与其余答案的代码量几乎相同) (2认同)

小智 6

使用checkdate函数验证:

$date = '2019-02-30';

$date_parts = explode( '-', $date );

if(checkdate( $date_parts[1], $date_parts[2], $date_parts[0] )){
    //date is valid
}else{
    //date is invalid
}
Run Code Online (Sandbox Code Playgroud)


小智 5

检查给定日期是否有效的最简单方法可能是使用将其转换为unixtime strtotime,将其格式化为给定日期的格式,然后进行比较:

function isValidDate($date) { return date('Y-m-d', strtotime($date)) === $date; }

当然,您可以使用正则表达式来检查有效性,但是它将限于给定的格式,每次您必须对其进行编辑以满足其他格式时,它也会超出要求。内置功能是完成工作的最佳方法(在大多数情况下)。

  • 这是最短的答案,并且有效。很难说这是低质量的。 (3认同)