我从API接收到一个日期字符串,它的格式为yyyy-mm-dd
。
我目前使用正则表达式验证字符串格式,这个方法还不错,但是我发现有一些情况下,即使按照字符串的格式来看也可能是无效的日期,比如2013-13-01
。
在PHP中,有没有更好的方法来判断像2013-13-01
这样的字符串是否是符合yyyy-mm-dd
格式的有效日期?
DateTime::createFromFormat()
来实现这个目的: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;
}
[该函数取自此答案。也在php.net上。最初由Glavić编写。]
测试用例:
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
strtotime
函数获取 Unix 时间戳,然后使用 date('Y-m-d', $t)
函数获取日期字符串。然后,您可以像这个答案一样进行比较。 - pedromanoelstrtotime
函数进行转换。但是对于strtotime
无法识别的非标准格式,您需要另寻他法。另外,PHP版本5.2支持已于2011年1月停止,5.3支持已于2014年8月停止。 - Glavićvar_dump( validateDate('2012-2-9'));
- reignsly'Y-n-j'
,@reignsly。 - Amal Murali$d
将不会是false。但这真的取决于你想要什么。如果你需要例如validateDate('2015-55-66')
是有效的,那么是的,你只需要检查$d
是否为对象即可。 - Glavić确定任何字符串是否为日期
function checkIsAValidDate($myDateString){
return (bool)strtotime($myDateString);
}
yyyy-mm-dd
。 - EWitreturn (bool)strtotime($myDateString) && date("Y-m-d", strtotime($myDateString)) == $myDateString;
来解决该问题。 - elitechief21(bool)strtotime('s')
的结果是true? - Peon使用PHP预置函数,以简单的方式进行操作:
function checkmydate($date) {
$tempDate = explode('-', $date);
// checkdate(month, day, year)
return checkdate($tempDate[1], $tempDate[2], $tempDate[0]);
}
测试
checkmydate('2015-12-01'); //true
checkmydate('2015-14-04'); //false
if
语句中返回 true
或 false
,应该直接返回测试本身。 - Victor Schröder返回 sizeof($tmpDate) == 3 && checkdate($tmpDate[1]...
- neurino2
,20
,202
,2020
,甚至是20201
,每次都会返回true。 - rolingercheckmydate('thisIsWrong!')
,则会抛出通知。 - nulll确定字符串是否为日期,即使字符串是非标准格式
(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');
if
语句中使用测试来返回true
或false
时,应该返回测试本身。 - Victor Schröder这个选项不仅简单易用,而且几乎可以接受任何格式,尽管对于非标准格式可能会有一些问题。
$timestamp = strtotime($date);
return $timestamp ? $date : null;
检查给定日期是否有效的最简单方法可能是使用strtotime
将其转换为Unix时间,将其格式化为给定日期的格式,然后进行比较:
function isValidDate($date) {
return date('Y-m-d', strtotime($date)) === $date;
}
当然,您可以使用正则表达式来检查有效性,但它将仅限于给定格式,每次您都必须编辑它以满足其他格式,并且这将超出所需。内置函数是实现任务的最佳方式(在大多数情况下)。
checkdate()
函数,但我发现如果年份为任何值,checkdate()
都会失败:2、20、202、2020、20201
- 都会返回true。我选择采用您的解决方案! - rolinger很遗憾,最受欢迎的解决方案(https://dev59.com/s2Ik5IYBdhLWcg3wbtyb#19271434)并没有正常工作。第四个测试用例 (var_dump(validateDate('2012-2-25')); // false) 是错的。日期是正确的,因为它符合格式 - m 允许一个带或不带前导零的月份(请参阅:http://php.net/manual/en/datetime.createfromformat.php)。因此,日期2012-2-25 是以Y-m-d 格式呈现的,测试用例必须是真的而不是假的。
我认为更好的解决方法是按照以下方式测试可能的错误:
function validateDate($date, $format = 'Y-m-d') {
DateTime::createFromFormat($format, $date);
$errors = DateTime::getLastErrors();
return $errors['warning_count'] === 0 && $errors['error_count'] === 0;
}
您也可以解析日期并获取月、日和年,然后使用PHP函数checkdate()
进行验证。您可以在此处阅读有关该函数的信息:http://php.net/manual/zh/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';
}
我有这样一种想法,即使是在PHP中,我也喜欢找到功能性解决方案。例如,@migli提供的答案非常好,高度灵活和优雅。
但它有一个问题:如果您需要验证许多具有相同格式的DateTime字符串怎么办?您将不得不在所有地方重复使用格式,这与DRY原则相违背。我们可以将格式放在常量中,但仍然需要将常量作为参数传递给每个函数调用。
但不要担心!我们可以使用柯里化来解决问题!PHP并不会让这项任务变得愉快,但仍然可以在PHP中实现柯里化:
<?php
function validateDateTime($format)
{
return function($dateStr) use ($format) {
$date = DateTime::createFromFormat($format, $dateStr);
return $date && $date->format($format) === $dateStr;
};
}
那么,我们刚才做了什么?基本上,我们将函数体包装在一个匿名函数中,并返回这样的函数。我们可以像这样调用验证函数:
validateDateTime('Y-m-d H:i:s')('2017-02-06 17:07:11'); // true
是的,这并没有太大差别…但真正的威力来自于部分应用函数,这得益于柯里化:
// 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
函数式编程太棒了!
function checkmydate($date) {
$tempDate = explode('-', $date);
return checkdate($tempDate[1], $tempDate[2], $tempDate[0]);
}
测试
checkmydate('2015-12-01');//true
checkmydate('2015-14-04');//false
count($tempDate) === 3
。 - VDarricau