Статьи

Повлияло ли ваше PHP-приложение на ошибку Y2K38?

Я не хочу быть слишком паникером, но попробуйте запустить следующий код PHP в вашей системе:


<?php
$date = '2040-02-01';
$format = 'l d F Y H:i';

$mydate1 = strtotime($date);
echo '<p>', date($format, $mydate1), '</p>';
?>

Если повезет, в вашем браузере отобразится «Среда 1 февраля 2040 00:00» . Если вы видите дату в конце 60-х или начале 70-х, ваше PHP-приложение может оказаться под угрозой из-за ошибки Y2K38!

Что за ошибка Y2K38?

Y2K38, или Unix Millennium Bug, влияет на PHP и многие другие языки и системы, которые используют 32-разрядное целое число со знаком для представления даты в виде количества секунд с 00:00:00 UTC 1 января 1970 года. Самая поздняя дата, которая может быть сохранено 03:14:07 UTC 19 января 2038 года. Кроме того, устанавливается крайний левый бит, а целое становится отрицательным десятичным числом — или временем, предшествующим эпохе.

Да, прошло 28 лет, и я уверен, что многие из вас думают, что сейчас смешно беспокоиться об этом. Тем не менее, разработчики думали так об ошибке Millennium 1970-х и 80-х годов. Кроме того, любое веб-приложение, которое обрабатывает долгосрочные будущие события, может быть в опасности. Например, типичная ипотека работает на 25 лет. Пенсии и накопительные планы могут быть намного дольше.

Спасет ли нас 64-бит?

Наверное. Если вы используете 64-битную ОС с скомпилированной 64-битной версией PHP, это не должно повлиять на ваше приложение. Я бы порекомендовал вам проверить это. 64-разрядное число со знаком дает максимальную будущую дату, которая в 21 раз больше, чем текущий возраст вселенной — 292 миллиарда лет, день или ночь, день или два.

Вы можете спать по ночам, если уверены, что ваше финансовое приложение всегда будет установлено в 64-битной системе.

Есть ли альтернативные варианты?

К счастью, PHP представил новый класс DateTime в версии 5.2 (экспериментальная поддержка была доступна в 5.1, и имейте в виду, что некоторые методы были введены в 5.3)…

 
<?php
$date = '2040-02-01';
$format = 'l j F Y H:i';

$mydate2 = new DateTime($date);
echo '<p>', $mydate2->format($format), '</p>';
?>

DateTime не страдает от проблем, связанных с Y2K38, и с радостью обработает даты до 31 декабря 9999 года. Возможно, к тому времени я заплатил по ипотеке!

Возможно, не стоит обновлять существующие приложения, но вы обязательно должны учитывать класс DateTime при планировании вашего следующего проекта.

Были ли у вас проблемы с Y2K38 в вашем приложении? Как ты это починил?