Правильно определите, является ли строка даты допустимой датой в этом формате

Я получаю строку даты из API, и она отформатирована как yyyy-mm-dd .

В настоящее время я использую регулярное выражение для проверки строкового формата, который работает нормально, но я вижу некоторые случаи, когда он может быть правильным форматом в соответствии с строкой, но на самом деле является недопустимой датой. т.е. 2013-13-01 , например.

Есть ли лучший способ в PHP взять строку, такую ​​как 2013-13-01 и сказать, является ли она допустимой датой или нет для формата yyyy-mm-dd ?

Для этого вы можете использовать класс DateTime :

 function validateDate($date, $format = 'Ym-d') { $d = DateTime::createFromFormat($format, $date); 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 

Демо!

Определите, является ли какая-либо строка датой

 function checkIsAValidDate($myDateString){ return (bool)strtotime($myDateString); } 

Используйте простой способ с заранее созданной функцией 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 

Этот параметр не только прост, но и принимает практически любой формат, хотя с нестандартными форматами он может быть неисправен.

 $timestamp = strtotime($date); return $timestamp ? $date : null; 

Определите, является ли строка датой, даже если строка является нестандартным форматом

(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', 'Ymd H:i:s'); validateDateTime('2001-03-10', 'Ym-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', 'mdy'); validateDateTime('10, 3, 2001', 'j, n, Y'); validateDateTime('20010310', 'Ymd'); validateDateTime('05-16-18, 10-03-01', 'his, jm-y'); validateDateTime('Monday 8th of August 2005 03:12:46 PM', 'l jS \of FY h:i:s A'); validateDateTime('Wed, 25 Sep 2013 15:28:57', 'D, d MYH: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', 'YmD H:i:s'); validateDateTime('2001', 'm'); validateDateTime('Mon', 'Dm-y'); validateDateTime('Mon', 'Dm-y'); validateDateTime('2001-13-04', 'Ym-d'); 

Вы также можете проанализировать дату для даты и года месяца, а затем вы можете использовать функцию checkdate() функции PHP, которую вы можете прочитать здесь: 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'; } 

Соглашаясь с ответом cl-sah, но этот звук лучше, короче …

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

Контрольная работа

 checkmydate('2015-12-01');//true checkmydate('2015-14-04');//false 

У меня есть эта вещь, которая, даже с PHP, мне нравится находить функциональные решения. Так, например, ответ, данный @migli, действительно хороший, очень гибкий и элегантный.

Но у него есть проблема: что, если вам нужно проверить много строк DateTime в том же формате? Вам придется повторять формат повсюду, что противоречит принципу DRY . Мы могли бы поместить формат в константу, но все же нам пришлось бы передавать константу в качестве аргумента для каждого вызова функции.

Но больше не бойтесь! Мы можем использовать currying для нашего спасения! PHP не делает эту задачу приятной, но по-прежнему можно реализовать currying с PHP:

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

Итак, что мы только что сделали? В основном мы завернули тело функции анонимным и вернули такую ​​функцию. Мы можем вызвать функцию проверки следующим образом:

 validateDateTime('Ymd H:i:s')('2017-02-06 17:07:11'); // true 

Да, не большая разница … но реальная сила исходит от частично примененной функции , сделанной путем каррирования:

 // Get a partially applied function $validate = validateDateTime('Ymd 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 

Функциональное программирование FTW!

Протестированное решение для регулярных выражений:

  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; } 

Это вернет null, если дата недействительна или не имеет формат yyyy-mm-dd, иначе она вернет дату.

  /**** date check is a recursive function. it's need 3 argument MONTH,DAY,YEAR. ******/ $always_valid_date = $this->date_check($month,$day,$year); private function date_check($month,$day,$year){ /** checkdate() is a php function that check a date is valid or not. if valid date it's return true else false. **/ $status = checkdate($month,$day,$year); if($status == true){ $always_valid_date = $year . '-' . $month . '-' . $day; return $always_valid_date; }else{ $day = ($day - 1); /**recursive call**/ return $this->date_check($month,$day,$year); } } 

Как насчет этого?

Мы просто используем блок try-catch.

 $dateTime = 'an invalid datetime'; try { $dateTimeObject = new DateTime($dateTime); } catch (Exception $exc) { echo 'Do something with an invalid DateTime'; } 

Этот подход не ограничивается только одним форматом даты / времени, и вам не нужно определять какую-либо функцию.

Попробуйте:

 $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 "The function is working"; }else { echo "The function isNOT working"; } 

По словам Амала Мурали,

 $d = DateTime::createFromFormat('Ymd g:i:s', $date); $d2 = DateTime::createFromFormat('Ymd H:i:s', $date); if(($d && $d->format('Ymd g:i:s') == $date) || ($d2 && $d2->format('Ymd H:i:s') == $date)) { return true; } else { return false; } 

Самый простой способ проверить, действительно ли заданная дата действительна, вероятно, преобразует ее в unixtime с помощью strtotime , форматируя ее в формате данной даты, а затем сравнивая ее:

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

Конечно, вы можете использовать регулярное выражение для проверки достоверности, но оно будет ограничено заданным форматом, каждый раз, когда вам придется редактировать его, чтобы удовлетворить другие форматы, а также это будет более чем необходимо. Встроенные функции – лучший способ (в большинстве случаев) для достижения рабочих мест.