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

StackOverflow https://stackoverflow.com/questions/141315

  •  02-07-2019
  •  | 
  •  

Вопрос

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

$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 Ср. 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('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'

дата эха('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 года, я не думаю, что это должно работать в любом случае.

Ниже приведена функция, которую я использую для преобразования дат, таких как приведенные выше, во временную метку для сравнения и т.д., Которая может быть вам полезна для дат, выходящих за рамки "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);
}

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

см . strtotime - время

см . Gnu Calendar-дата-элементы.html

"Для числовых месяцев допускается стандарт ISO 8601 формат ‘год-месяц-день’, где year - любое положительное число, месяц - это число от 01 до 12, и день - это число между 01 и 31.A Начальный ноль должен присутствовать, если число меньше десяти. "

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


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

см . strftime ( время ожидания )


Использование дата проверки функция вместо этого (более надежная):

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

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

год:Тот Самый год - от 1 до 32 767 включительно.

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

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

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 ("Y-m-d, mktime (0, 0, 0, $month, $day, $year));
}
<?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

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

Просто измените формат, отредактировав строку скрипта ниже 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;
}
?>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top