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

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

$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???

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

Изменить: Люди спрашивают, что я запускаю: Запуск 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

Ответы

Ответ 1

От 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;
}
?>

Ответ 2

Как уже упоминалось здесь: 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'

Ответ 3

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

приводит к: "1999-11-30"

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

В mktime(), localtime(), strtotime() есть документально зарегистрированная ошибка mysql21 > , возвращающая это нечетное значение при попытке предварительной -epoch (включая "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);
}

Ответ 4

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

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

Ответ 5

Если вы просто хотите обработать преобразование даты без времени для поля даты 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));
}

Ответ 6

Эта версия позволяет пустому поле, имеет даты в формате 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;
}

Ответ 7

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

Просто измените формат, отредактировав строку ниже script 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" ;
    }
}
?>

Ответ 8

<?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

Ответ 9

Я использовал следующий код для проверки дат, поступающих из приложений 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);
}

Ответ 10

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