我从一个API接收到一个日期字符串,它的格式是yyyy-mm-dd。
我目前正在使用一个正则表达式来验证字符串格式,这是可以工作的,但我可以看到一些情况下,根据字符串,它可能是一个正确的格式,但实际上是一个无效的日期。例如,2013年13月1日。
在PHP中是否有更好的方法来获取一个字符串,如2013-13-01,并判断它是否是yyyy-mm-dd格式的有效日期?
我从一个API接收到一个日期字符串,它的格式是yyyy-mm-dd。
我目前正在使用一个正则表达式来验证字符串格式,这是可以工作的,但我可以看到一些情况下,根据字符串,它可能是一个正确的格式,但实际上是一个无效的日期。例如,2013年13月1日。
在PHP中是否有更好的方法来获取一个字符串,如2013-13-01,并判断它是否是yyyy-mm-dd格式的有效日期?
当前回答
要添加到已接受的答案上,可以通过检查格式化的日期是否是DateTime的实例来进一步检查有效日期或DateTime。
$date = DateTime::createFromFormat('Ymd', $value);
$is_datetime = ($date instanceof DateTime);
$is_valid_datetime_format = $is_datetime
? ($date->format('Ymd') === $value)
: false;
if (!$is_datetime || !$is_valid_datetime_format) {
// Not a valid date.
return false;
}
这将捕获任何不是DateTime的值,如随机字符串或无效日期,如20202020。
其他回答
我有这样的东西,即使使用PHP,我也喜欢寻找函数式解决方案。例如,@migli给出的答案非常好,非常灵活和优雅。
但它有一个问题:如果需要用相同的格式验证大量DateTime字符串怎么办?你将不得不到处重复这种格式,这违背了DRY原则。我们可以把格式放在一个常量中,但是,我们仍然必须把这个常量作为参数传递给每个函数调用。
但是不要再害怕了!我们可以用咖喱来拯救我们!PHP并没有让这个任务变得愉快,但仍然可以用PHP实现curry:
<?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
函数式编程!
测试过的Regex解决方案:
function isValidDate($date)
{
if (preg_match("/^(((((1[26]|2[048])00)|[12]\d([2468][048]|[13579][26]|0[48]))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|[12]\d))))|((([12]\d([02468][1235679]|[13579][01345789]))|((1[1345789]|2[1235679])00))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|1\d|2[0-8])))))$/", $date)) {
return $date;
}
return null;
}
如果日期无效或不是yyyy-mm-dd格式,将返回null,否则将返回日期。
判断是否有字符串是日期
function checkIsAValidDate($myDateString){
return (bool)strtotime($myDateString);
}
你可以使用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上也有。原作者:格拉维克。
测试用例:
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不接受任何自定义格式)
<?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');