php проверить действительную дату, странные преобразования даты

Есть ли способ проверить, действительно ли дата / время действительны, вы бы подумали, что это будет легко проверить:

$date = '0000-00-00'; $time = '00:00:00'; $dateTime = $date . ' ' . $time; if(strtotime($dateTime)) { // why is this valid? } 

что действительно меня заводит:

 echo date('Ym-d', strtotime($date)); 

результаты: "1999-11-30",

да? я пошел с 0000-00-00 до 1999-11-30 ???

Я знаю, что могу сделать сравнение, чтобы увидеть, является ли дата одним из этих значений, равна дате, которую я имею, но это не очень надежный способ проверки. Есть ли хороший способ проверить, есть ли у меня действительная дата? У кого-нибудь есть хорошая функция, чтобы проверить это?

Изменить: люди спрашивают, что я запускаю: Запуск PHP 5.2.5 (cli) (построено: июль 23 2008 11:32:27) на Linux localhost 2.6.18-53.1.14.el5 # 1 SMP Wed Mar 5 11 : 36: 49 EST 2008 i686 i686 i386 GNU / Linux

От php.net

 <?php function isValidDateTime($dateTime) { if (preg_match("/^(\d{4})-(\d{2})-(\d{2}) ([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/", $dateTime, $matches)) { if (checkdate($matches[2], $matches[3], $matches[1])) { return true; } } return false; } ?> 

Как уже упоминалось: https://bugs.php.net/bug.php?id=45647

Здесь нет ошибки, 00-00-00 означает 2000-00-00, что составляет 1999-12-00, что составляет 1999-11-30. Нет ошибок, совершенно нормально.

И, как показано несколькими испытаниями, откат назад ожидается поведением, если он немного тревожит:

 >> date('Ym-d', strtotime('2012-03-00')) string: '2012-02-29' >> date('Ym-d', strtotime('2012-02-00')) string: '2012-01-31' >> date('Ym-d', strtotime('2012-01-00')) string: '2011-12-31' >> date('Ym-d', strtotime('2012-00-00')) string: '2011-11-30' 

echo date ('Ym-d', strtotime ($ date));

результаты: "1999-11-30"

Результатом strtotime является 943920000 – это количество секунд, примерно, между эпохой Unix (база, из которой измеряется время) до 1999-11-30.

Существует документированная ошибка mysql для mktime(), localtime(), strtotime() возвращающих это странное значение, когда вы пытаетесь mktime(), localtime(), strtotime() предварительное время (включая «0000-00-00 00:00:00»). Есть некоторая дискуссия по связанной теме о том, действительно ли это ошибка:

Поскольку временная метка начинается с 1970 года, я не думаю, что она должна работать в любом случае.

Ниже приведена функция, которую я использую для преобразования dateTimes, таких как выше, в метку времени для сравнений и т. Д., Которые могут вам пригодиться, для дат, выходящих за пределы «0000-00-00 00:00:00»,

 /** * Converts strings of the format "YYYY-MM-DD HH:MM:SS" into php dates */ function convert_date_string($date_string) { list($date, $time) = explode(" ", $date_string); list($hours, $minutes, $seconds) = explode(":", $time); list($year, $month, $day) = explode("-", $date); return mktime($hours, $minutes, $seconds, $month, $day, $year); } 

Не ожидайте согласованных результатов, когда вы находитесь за пределами допустимого диапазона:

cf strtotime

cf Gnu Calendar-date-items .html

«Для числовых месяцев допускается формат ISO 8601« год-месяц-день », где год – любое положительное число, месяц – это число от 01 до 12 , а день – это число от 01 до 31. В качестве начального нуля должно быть если число меньше десяти ».

Так что «0000-00-00» дает странные результаты, это логично!


«Кроме того, не все платформы поддерживают отрицательные временные метки, поэтому диапазон дат может быть ограничен не ранее, чем в эпоху Unix . Это означает, что, например,% e,% T,% R и% D (может быть больше) и даты до 1 января 1970 года не будет работать в Windows, некоторых дистрибутивах Linux и нескольких других операционных системах ».

cf strftime


Вместо этого используйте функцию checkdate (более надежную):

месяц: месяц составляет от 1 до 12 включительно .

день: день находится в пределах разрешенного количества дней для данного месяца. Учитываются високосный год.

год: год составляет от 1 до 32767 включительно .

Эта версия позволяет пустому поле, имеет даты в формате mm / dd / yy или mm / dd / yyyy, допускает однократные часы, добавляет дополнительные am / pm и исправляет некоторые тонкие недостатки во времени.

Все еще допускает некоторые патологические времена, такие как «23: 14 AM».

 function isValidDateTime($dateTime) { if (trim($dateTime) == '') { return true; } if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{2,4})(\s+(([01]?[0-9])|(2[0-3]))(:[0-5][0-9]){0,2}(\s+(am|pm))?)?$/i', $dateTime, $matches)) { list($all,$mm,$dd,$year) = $matches; if ($year <= 99) { $year += 2000; } return checkdate($mm, $dd, $year); } return false; } 

Если вы просто хотите обработать преобразование даты без времени для поля даты mysql, вы можете изменить этот отличный код так же, как я. В моей версии PHP без выполнения этой функции я получаю «0000-00-00» каждый раз. Раздражает.

 function ConvertDateString ($DateString) { list($year, $month, $day) = explode("-", $DateString); return date ("Ymd, mktime (0, 0, 0, $month, $day, $year)); } 
 <?php function is_valid_date($user_date=false, $valid_date = "1900-01-01") { $user_date = date("Ymd H:i:s",strtotime($user_date)); return strtotime($user_date) >= strtotime($valid_date) ? true : false; } echo is_valid_date("00-00-00") ? 1 : 0; // return 0 echo is_valid_date("3/5/2011") ? 1 : 0; // return 1 

Я просто изменил ответ martin выше, который будет проверять любой тип даты и возвращения в формате, который вам нравится.

Просто измените формат, отредактировав ниже строку сценария strftime («10-10-2012», strtotime ($ dt));

 <?php echo is_date("13/04/10"); function is_date( $str ) { $flag = strpos($str, '/'); if(intval($flag)<=0){ $stamp = strtotime( $str ); } else { list($d, $m, $y) = explode('/', $str); $stamp = strtotime("$d-$m-$y"); } //var_dump($stamp) ; if (!is_numeric($stamp)) { //echo "ho" ; return "not a date" ; } $month = date( 'n', $stamp ); // use n to get date in correct format $day = date( 'd', $stamp ); $year = date( 'Y', $stamp ); if (checkdate($month, $day, $year)) { $dt = "$year-$month-$day" ; return strftime("%d-%b-%Y", strtotime($dt)); //return TRUE; } else { return "not a date" ; } } ?> 

Я использовал следующий код для проверки дат, поступающих из приложений ExtJS.

 function check_sql_date_format($date) { $date = substr($date, 0, 10); list($year, $month, $day) = explode('-', $date); if (!is_numeric($year) || !is_numeric($month) || !is_numeric($day)) { return false; } return checkdate($month, $day, $year); } 
 <?php function is_date( $str ) { $stamp = strtotime( $str ); if (!is_numeric($stamp)) { return FALSE; } $month = date( 'm', $stamp ); $day = date( 'd', $stamp ); $year = date( 'Y', $stamp ); if (checkdate($month, $day, $year)) { return TRUE; } return FALSE; } ?>