проверка php на правильную дату, странные преобразования даты - PullRequest
13 голосов
/ 26 сентября 2008

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

$date = '0000-00-00';
$time = '00:00:00';
$dateTime = $date . ' ' . $time;

if(strtotime($dateTime)) {
    // why is this valid?
}

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

echo date('Y-m-d', strtotime($date)); 

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

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

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

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

Ответы [ 10 ]

23 голосов
/ 26 сентября 2008

С 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;
}
?>
5 голосов
/ 30 марта 2012

Как упомянуто здесь: https://bugs.php.net/bug.php?id=45647

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

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

>> date('Y-m-d', strtotime('2012-03-00'))
string: '2012-02-29'
>> date('Y-m-d', strtotime('2012-02-00'))
string: '2012-01-31'
>> date('Y-m-d', strtotime('2012-01-00'))
string: '2011-12-31'
>> date('Y-m-d', strtotime('2012-00-00'))
string: '2011-11-30'
2 голосов
/ 26 сентября 2008

дата эха ('Y-m-d', strtotime ($ date));

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

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

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

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

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

/**
 * 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);
}
1 голос
/ 05 января 2011

Эта версия допускает, чтобы поле было пустым, имеет даты в формате мм / дд / гг или мм / дд / гггг, допускает однозначные часы, добавляет необязательные значения 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;
}
1 голос
/ 15 января 2010

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

function ConvertDateString ($DateString)
{
    list($year, $month, $day) = explode("-", $DateString);
    return date ("Y-m-d, mktime (0, 0, 0, $month, $day, $year));
}
1 голос
/ 29 сентября 2008

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

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 включительно .

0 голосов
/ 25 апреля 2012

Я использовал следующий код для проверки дат, поступающих из приложений 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);
}
0 голосов
/ 16 марта 2012
<?php
function is_valid_date($user_date=false, $valid_date = "1900-01-01") {
    $user_date = date("Y-m-d 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
0 голосов
/ 20 января 2012

Я только что изменил ответ 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" ;
    }
}
?>
0 голосов
/ 19 сентября 2011
<?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;
}
?>
...