PHP: strtotime возвращает false для будущей даты?

вот несколько отладочных выражений, которые я вставил в eclipse, если вы мне не верите:

"strtotime("2110-07-16 10:07:47")" = (boolean) false    
"strtotime("2110-07-16")" = (boolean) false 

я использую его в своей функции, которая возвращает случайную дату между начальной и конечной датами:

public static function randomDate($start_date, $end_date, $format = DateTimeHelper::DATE_FORMAT_SQL_DATE)
    {
        if($start_date instanceof DateTime)     $start_date = $start_date->format(DateTimeHelper::DATE_FORMAT_YMDHMS);
        if($end_date instanceof DateTime)       $end_date   = $end_date->format(DateTimeHelper::DATE_FORMAT_YMDHMS);

        // Convert timetamps to millis
        $min = strtotime($start_date);
        $max = strtotime($end_date);

        // Generate random number using above bounds
        $val = rand($min, $max);

        // Convert back to desired date format
        return date($format, $val);
    }

есть идеи, как заставить его вернуть правильное время unix для будущей даты?

Благодарность!


person Garrett    schedule 16.07.2010    source источник
comment
Мы верим вам, за исключением ожидаемого поведения для значений даты, которые вы передаете, которые выходят за пределы диапазона дат 32-разрядного PHP.   -  person Mark Baker    schedule 16.07.2010
comment
Из документации PHP: допустимый диапазон метки времени обычно составляет от пятницы, 13 декабря 1901 г., 20:45:54 UTC до вторника, 19 января 2038 г., 03:14:07 UTC. (Это даты, которые соответствуют минимальному и максимальному значениям для 32-разрядного целого числа со знаком.) Кроме того, не все платформы поддерживают отрицательные метки времени, поэтому ваш диапазон дат может быть ограничен не ранее эпохи Unix. Это означает, что, например. даты до 1 января 1970 года не будут работать в Windows, некоторых дистрибутивах Linux и некоторых других операционных системах. Однако PHP 5.1.0 и более новые версии преодолевают это ограничение.   -  person Ivar Bonsaksen    schedule 16.07.2010
comment
я использую php 5.3 = S 5.2 на моем реальном сервере. тогда не должно работать?   -  person Garrett    schedule 16.07.2010
comment
Нет, PHP 5.1.0+ исправляет, кроме того, не все платформы поддерживают бит отрицательных временных меток, а не бит до вторника, 19 января 2038 года.   -  person Lightness Races in Orbit    schedule 16.03.2011


Ответы (5)


Если вы хотите работать с датами, выходящими за пределы диапазона 32-битных целых чисел, используйте объекты PHP dateTime.

try {
    $date = new DateTime('2110-07-16 10:07:47');
} catch (Exception $e) {
    echo $e->getMessage();
    exit(1);
}

echo $date->format('Y-m-d');
person Mark Baker    schedule 16.07.2010
comment
на самом деле, похоже, что это убьет мою функцию randomDate. как я могу сделать случайную дату с DateTime? - person Garrett; 16.07.2010
comment
как этот ответ принимается, когда вопрос заключался в том, как получить временную метку unix? - person mvds; 16.07.2010
comment
Объекты dateTime uk2.php.net/manual/en/book.datetime.php доступны начиная с версии PHP 5.2.0 и используют внутри себя 64-битное целое число, что дает диапазон дат от примерно 292 миллиардов лет назад до примерно 292 миллиардов лет в будущем. Этого должно быть достаточно для большинства приложений, если вы не палеобиолог. - person Mark Baker; 16.07.2010
comment
@mvds, потому что вы можете вызвать format() с U, чтобы вернуть Unixtime. См. php.net/manual/en/datetime.format.php и php.net/manual/en/function.date.php. - person floriank; 03.06.2013

Постарайтесь сохранить его до вторника, 19 января 2038 г., 03:14:07 UTC, когда эпоха меток времени unix для 32-битных систем перевернется!

Это даже описано в руководстве по адресу http://php.net/strtotime.

изменить: Только что протестировано: проблема исправлена ​​путем установки 64-битной ОС и соответствующей 64-битной версии php. Думаю, у нас достаточно времени, чтобы исправить ошибку реинкарнированного миллениума:

$one = strtotime("9999-12-31 23:59:59");  
$two = strtotime("10000-01-01 00:00:00");
var_dump($one);
var_dump($two);

int(253402297199)
bool(false)
person mvds    schedule 16.07.2010
comment
Re: Изменить. Обратите внимание, что 64-разрядный PHP (потокобезопасный VC9) в 64-разрядной версии Vista по-прежнему использует диапазон 32-разрядных целых чисел со знаком для значений даты. - person Mark Baker; 16.07.2010
comment
Я предполагаю, что это связано с тем, что strtotime() не является функцией php, а просто частью канала для подключения к (g) libc (по крайней мере, в стране unix) - person mvds; 16.07.2010
comment
Возможно, я был довольно раздражен, когда обнаружил это во время недавнего тестирования даты на различных платформах. Также интересно отметить, что форматы строки даты, передаваемые конструктору dateTime, принимают ряд форматов, которые strtotime отклонит; но я не смотрел на внутренности, чтобы увидеть, что они используют - person Mark Baker; 16.07.2010

Из руководства по PHP:

Допустимый диапазон метки времени обычно составляет от пятницы, 13 декабря 1901 года, 20:45:54 по Гринвичу, до вторника, 19 января 2038 года, 03:14:07 по Гринвичу. (Это даты, соответствующие минимальному и максимальному значениям для 32-битного целого числа со знаком). Однако до PHP 5.1.0 этот диапазон был ограничен с 01-01-1970 до 19-01-2038 в некоторых системах (например, Windows).

См. также: Задача 2038 года — Википедия

person igorw    schedule 16.07.2010

Вы не можете конвертировать даты, которые происходят после смены времени unix (2038)

person PaulJWilliams    schedule 16.07.2010
comment
Гах... Избит, как рыжий пасынок. - person PaulJWilliams; 16.07.2010

Простая замена strtotime

$date = '2199-12-31T08:00:00.000-06:00';

echo date('Y-m-d', strtotime($date)); // fails with 1970 result

echo date_format(  date_create($date) , 'Y-m-d'); // works perfect with 5.2+

Фактическое сообщение здесь.

person Azghanvi    schedule 24.04.2015
comment
не печатает дату сэр - person Waqas_aamer; 19.08.2016