Работаем с датами широкого диапазона в PHP

Многие не задумываются при работе в PHP со стандартными функциями даты-времени о диапазоне их применимости (date(), time(), mktime() и т.п). Так мы можем скоро столкнуться с проблемой, подобная которой случалась уже раньше — «ошибка 2000». Я прекрасно помню сколько об этом говорилось и писалось в своё время. Сейчас проблему можно будет называть как «ошибка 2038».

Проблема 2038 года.

«Ошибка 2000» заключалась в неверной интерпретации в старых программах наступления 2000 года. Когда по логике программы, которая хранила только два младших годичных разряда, после 1999 наступал не 2000-й год, а 1900-й.

В нашем случае множество 32-битных UNIX-приложений, хранящих время в виде UNIX_TIMESTAMP рискуют начать массово отказываться работать исправно где то 19 января 2038 года. Это как раз та дата, когда 32-битное целое число со знаком, используемое для хранения времени в секундах с 01 января 1900 года, будет переполнено. Осталось до этого момента совсем немного — 22 года.

Чем ближе мы к этой дате (а многие алгоритмы используют опережающие текущее время расчеты), тем больше вероятность сбоев. И если в 2000-м году было не так то много компьютеров, кол-во вычислительных устройств на душу населения было не велико, то в наше время (а тем более через 20 лет) это будет значительная величина. Проконтролировать, обновить, исправить весь софт будет очень сложно. Думать об этом стоит уже сейчас.

Работа с датами позднее 2038 (и ранее  1900 года).

Я не стал бы начинать этот разговор, если бы не показал какие то пути решения.

Во первых, наверняка, одним из решений будет расширение переменной до 64 бит, что позволит охватить период в 292 млрд. лет. Так сохранят совместимость со старыми программами, хотя их нужно будет перекомпилировать, выполнить какие то обновления баз данных и т.п.

А ещё через 250 млрд. лет переменную расширят до 1024 битов, на тот случай, если вселенная все же развивается не циклично (пару слов о большом взрыве) :).

Нужно привыкать работать в бóльших пределах времени. Пока человечество проживает на Земле, то нам совершенно естественны годичные временные циклы (подсчет витков Земли вокруг Солнца). Сложно сказать, когда мы откажемся от подобного исчисления. Скорее всего ещё долго после колонизации других миров, наши предки будут считать время в земных годах. Во всяком случае, если годичные циклы вряд ли сохранятся в далеком будущем, то период в 1 секунду не имеет каких либо предпосылок к замене и тогда. Т.е. хранение времени в виде кол-ва секунд, начиная с какого то исторического момента, будет иметь место и далее.

Расширение разрядности, впрочем, не решает другой проблемы — представления дат до 1900 года. Я бы использовал для этого отрицательные значения, но пока так не делают. Возможно, догадаются позже :).

Возвращаясь от теории к практики, т.е. к PHP, мы имеем два хороших решения. Одно из них — это использование класса DateTime. Второе решение мы находим, помня о том, с чем обычно в связке используется PHP. Это — базы данных, в которых мы чаще всего имеем богатый арсенал работы с таким типом данных как DATETIME. Из баз данных я буду рассматривать MySQL, для конкретики.

Класс PHP DateTime.

Данный класс позволяет работать со временем в пределах от ‘0000-00-00 00:00:00’ до ‘9999-12-31 23:59:59’. Что далеко за пределами unix epoch. Этот класс вообще-то работает ещё в бóльших пределах. Попробуйте, к примеру, вот такой код:

Но инициализировать объект датой старше 10000 года вам не удастся, потому будем считать, что названный выше диапазон является рабочим.

Так как форматирование даты совместимо с форматом функции date(), то вы сможете получить любую «привычную» информацию о дате.

Тип данных DATETIME в MySQL.

Данный тип хранения времени охватывает диапазон времени (согласно документации) от ‘1000-01-01 00:00:00’ до ‘9999-12-31 23:59:59’. На 1000 лет поменьше, чем первый вариант :), но гораздо шире unix epoch.

Вычисления не затрагивают хранилища данных, мы не обращаемся к таблицам. Запросы будут выполняться очень быстро. Но все же это обращение к «внешнему» источнику данных (другой программе, библиотеке). Надо постараться уменьшить число таких запросов. Сервер баз данных может находиться на другом компьютере, и обращение к ней будет путешествовать по локальной сети.

Вот пример такого запроса, где мы выполняем ряд нужных нам расчетов даты и времени.

Написать комментарий

Мало букафф? Читайте есчо !

Конвертируем в PDF

Сентябрь 3, 2013 г.

Есть несколько задач, связанных с конвертацией документов в PDF. Меня интересует перевод из HTML и создание PDF средствами PHP. Конвертировать страницу, отображенную в браузере в PDF. Здесь обычно используют плагины. Это работает до тех пор, пока ...

Читать

Замена первого/последнего значения в строке на PHP

Октябрь 28, 2022 г.

Задача - заменить первое/последнее искомое значение в заданной строке. В PHP много уделяется внимания работы со строками, но вот оптимального решения для этой задачи нет. Функция str_replace, заменяет все значения, но может посчитать вам сколько ...

Читать

 

Комментарии к «Работаем с датами широкого диапазона в PHP»

Понравилась статья? Есть вопросы? - пишите в комментариях.



Комментарий: