Я получаю строку даты из API, и она отформатирована как «yyyy-mm-dd».
В настоящее время я использую regex для проверки формата строки, что работает нормально, но бывают некоторые случаи, когда это может быть правильный формат, согласно строке, но на самом деле дата недействительна. Например, 2020-13-01.
Есть ли в PHP лучший способ взять строку 2020-13-01 и определить, является ли она действительной датой для формата «yyyy-mm-dd»?
Ответ 1
Для этого можно использовать DateTime::createFromFormat():
function validateDate($date, $format = 'Y-m-d') {
$d = DateTime::createFromFormat($format, $date);
// Y (4-значный год) возвращает TRUE для любого целого числа с любым количеством цифр, поэтому изменение сравнения с == на === устраняет проблему.
return $d && $d->format($format) === $date;
}
Тестовые варианты:
var_dump(validateDate('2020-13-01')); // false
var_dump(validateDate('20202-13-01')); // false
var_dump(validateDate('2020-11-32')); // false
var_dump(validateDate('2019-2-25')); // false
var_dump(validateDate('2020-12-01')); // true
var_dump(validateDate('1970-12-01')); // true
var_dump(validateDate('2019-02-29')); // true
var_dump(validateDate('2019', 'Y')); // true
var_dump(validateDate('12012', 'Y')); // false
Ответ 2
Используйте простой способ с помощью встроенной функции 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
Ответ 3
Определяет, является ли строка датой, даже если строка имеет нестандартный формат (strtotime не принимает нестандартный формат):
<?php
function validateDateTime($dateStr, $format) {
date_default_timezone_set('UTC');
$date = DateTime::createFromFormat($format, $dateStr);
return $date && ($date->format($format) === $dateStr);
}
// Эти возвращают 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');
// Эти возвращают 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');
Ответ 4
Самый простой способ проверить, действительна ли заданная дата, — это преобразовать ее в unixtime с помощью strtotime, отформатировать в формат заданной даты, а затем сравнить:
function isValidDate($date) {
return date('Y-m-d', strtotime($date)) === $date;
}
Конечно, вы можете использовать регулярное выражение для проверки валидности, но оно будет ограничено заданным форматом, и каждый раз вам придется редактировать его, чтобы проверить на другой формат, а также это будет занимать больше времени, чем требуется. Встроенные функции — лучший способ (в большинстве случаев) для достижения поставленных задач.
Ответ 5
У меня есть одна особенность: даже в PHP мне нравится находить функциональные решения.
Но у этого подхода есть проблема: что если вам нужно проверить множество строк 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
Да, разница невелика... но настоящий выигрыш исходит от частично применяемой функции, что стало возможным благодаря керрингу:
// Получение частично примененной функции
$validate = validateDateTime('Y-m-d H:i:s');
// Теперь вы можете использовать его везде, не повторяя проверку на формат!
$validate('2017-02-06 17:09:31'); // true
$validate('1999-03-31 07:07:07'); // true
$validate('13-2-4 3:2:45'); // false
Ответ 6
Попробуйте это:
$date = "2017-10-01";
function date_checker($input,$devider){
$output = false;
$input = explode($devider, $input);
$year = $input[0];
$month = $input[1];
$day = $input[2];
if (is_numeric($year) && is_numeric($month) && is_numeric($day)) {
if (strlen($year) == 4 && strlen($month) == 2 && strlen($day) == 2) {
$output = true;
}
}
return $output;
}
if (date_checker($date, '-')) {
echo "Функция выполнилась успешно";
}else {
echo "Ошибка при выполнении функции";
}
Web