PHP & mySQL: Год 2038 Ошибка: что это такое? Как его решить?

Я думал использовать TIMESTAMP для хранения даты + времени, но я читал, что на нем существует ограничение на 2038 год. Вместо того, чтобы задавать мой вопрос навалом, я предпочел разбить его на мелкие части, чтобы пользователям начинающих было легко понять их. Итак, мой вопрос (ы):

  1. Что такое проблема 2038 года?
  2. Почему это происходит и что происходит, когда это происходит?
  3. Как мы его решаем?
  4. Существуют ли какие-либо возможные альтернативы его использованию, которые не создают подобной проблемы?
  5. Что мы можем сделать с существующими приложениями, использующими TIMESTAMP, чтобы избежать так называемой проблемы, когда это действительно происходит?

Заранее спасибо.

    Я отметил это как сообщество wiki, поэтому не стесняйтесь редактировать в свободное время.

    Что такое проблема 2038 года?

    «Проблема 2038 года (также известная как Unix Millennium Bug, Y2K38 по аналогии с проблемой Y2K) может привести к сбою некоторых компьютерных программ до или в 2038 году. Проблема затрагивает все программное обеспечение и системы, которые хранят системное время в качестве подписанного 32 -битное целое число и интерпретировать это число как число секунд с 00:00:00 UTC 1 января 1970 года. "


    Почему это происходит и что происходит, когда это происходит?

    Время после 03:14:07 UTC во вторник, 19 января 2038 года, « обернется» и будет храниться внутри страны как отрицательное число, которое эти системы будут интерпретировать как время в 13 декабря 1901 года, а не в 2038 году. Это связано с тем, тот факт, что количество секунд с момента UNIX (1 января 1970 года 00:00:00 GMT) превысит максимальное значение для 32-разрядного целого числа со знаком.


    Как мы его решаем?

    • Используйте длинные типы данных (достаточно 64 бит)
    • Для MySQL (или MariaDB), если вам не нужна информация о времени, используйте тип столбца DATE . Если вам нужна более высокая точность, используйте DATETIME а не TIMESTAMP . Помните, что столбцы DATETIME не хранят информацию о часовом поясе, поэтому ваше приложение должно будет знать, какой часовой пояс использовался.
    • Другие возможные решения, описанные в Википедии
    • Подождите, пока разработчики MySQL исправят эту ошибку, о которой сообщалось более десяти лет назад.

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

    Попробуйте, где возможно, использовать большие типы для хранения дат в базах данных: достаточно 64 бит – длинный длинный тип в GNU C и POSIX / SuS, или sprintf('%u'...) в PHP или расширение BCmath.


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

    Таким образом, MySQL DATETIME имеет диапазон 1000-9999, но TIMESTAMP имеет диапазон 1970-2038. Если ваша система хранит даты рождения, будущие форвардные даты (например, 30-летние ипотечные кредиты) или аналогичные, вы уже столкнетесь с этой ошибкой. Опять же, не используйте TIMESTAMP, если это будет проблемой.


    Что мы можем сделать с существующими приложениями, использующими TIMESTAMP, чтобы избежать так называемой проблемы, когда это действительно происходит?

    Немногие PHP-приложения по-прежнему будут в 2038 году, хотя трудно предвидеть, что веб-платформа вряд ли является старой платформой.

    Ниже приведен процесс изменения столбца таблицы базы данных для преобразования TIMESTAMP в DATETIME . Он начинается с создания временного столбца:

     # rename the old TIMESTAMP field ALTER TABLE `myTable` CHANGE `myTimestamp` `temp_myTimestamp` int(11) NOT NULL; # create a new DATETIME column of the same name as your old column ALTER TABLE `myTable` ADD `myTimestamp` DATETIME NOT NULL; # update all rows by populating your new DATETIME field UPDATE `myTable` SET `myTimestamp` = FROM_UNIXTIME(temp_myTimestamp); # remove the temporary column ALTER TABLE `myTable` DROP `temp_myTimestamp` 

    Ресурсы

    • Год 2038 Проблема (Википедия)
    • Интернет закончится через 30 лет

    При использовании временных меток UNIX для хранения дат на самом деле вы используете 32-битные целые числа, которые подсчитывают количество секунд с 1970-01-01; см. Unix Time

    Это число из 32 бит будет переполняться в 2038 году. Это проблема 2038.

    Чтобы решить эту проблему, вы не должны использовать 32-битную временную метку UNIX для хранения ваших дат, а это значит, что при использовании MySQL вы не должны использовать TIMESTAMP , а DATETIME (см. 10.3.1. Типы DATETIME, DATE и TIMESTAMP ) :

    Тип DATETIME используется, когда вам нужны значения, которые содержат информацию о дате и времени. Поддерживаемый диапазон: '1000-01-01 00:00:00' до '9999-12-31 23:59:59' .

    Тип данных TIMESTAMP имеет диапазон '1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07' UTC.

    Лучшее, что вы можете сделать для своего приложения, чтобы избежать / исправить эту проблему, – это не использовать TIMESTAMP , а DATETIME для столбцов, которые должны содержать даты, которые не находятся между 1970 и 2038 годами.

    Одна небольшая заметка: хотя существует очень высокая вероятность (статистически), что ваше приложение будет переписано довольно много раз до 2038 года. ^ Так что, возможно, если вам не придется иметь дело с датами в будущем , вам не придется заботиться об этой проблеме с текущей версией вашего приложения …

    Быстрый поиск в Google сделает трюк: проблема 2038 года

    1. Проблема 2038 года (также известная как Unix Millennium Bug, Y2K38 по аналогии с проблемой Y2K) может привести к сбою некоторых компьютерных программ до или в 2038 году
    2. Проблема затрагивает все программное обеспечение и системы, которые хранят системное время как подписанное 32-битное целое число, и интерпретируют это число как количество секунд с 00:00:00 по UTC 1 января 1970 года. Последнее время, которое может быть представлено таким образом это 03:14:07 UTC во вторник, 19 января 2038 года. Времена за этот момент «обернутся» и будут храниться внутри страны как отрицательное число, которое эти системы будут интерпретировать как дату в 1901 году, а не 2038
    3. Нетрудно исправить эту проблему для существующих комбинаций ЦП / ОС, существующих файловых систем или существующих двоичных форматов данных

    http://en.wikipedia.org/wiki/Year_2038_problem имеет большую часть информации

    В итоге:

    1) + 2) Проблема заключается в том, что многие системы хранят информацию о дате как 32-разрядную подписанную int, равную количеству секунд с 1/1/1970. Самая последняя дата, которая может быть сохранена следующим образом: 03:14:07 UTC во вторник, 19 января 2038 года. Когда это произойдет, int «обернется» и будет сохранен как отрицательное число, которое будет интерпретировано как дата в 1901 году. То, что именно произойдет тогда, варьируется от системы к системе, но достаточно сказать, что это, вероятно, не будет хорошо для любого из них!

    Для систем, которые хранят только даты в прошлом, я думаю, вам не нужно беспокоиться какое-то время! Основная проблема заключается в системах, которые работают с датами в будущем. Если ваша система должна работать с датами 28 лет в будущем, тогда вы должны начать беспокоиться сейчас!

    3) Используйте один из альтернативных форматов даты или перейдите в 64-битную систему и используйте 64-битные int. Или для баз данных используется альтернативный формат штампа времени (например, для MySQL используется DATETIME)

    4) См. 3!

    5) См. 4 !!! 😉

    Bros, если вам нужно использовать PHP для отображения временных меток, это BEST PHP-решение без изменения формата UNIX_TIMESTAMP.

    Используйте функцию custom_date (). Внутри него используйте DateTime. Вот решение DateTime .

    Пока вы используете UNSIGNED BIGINT (8) в качестве временных меток в базе данных. Пока у вас есть PHP 5.2.0 ++

    Поскольку я не хотел ничего обновлять, я попросил мой backend (MSSQL) выполнить эту работу вместо PHP!

     $qry = "select DATEADD(month, 1, :date) next_date "; $rs_tmp = $pdo->prepare($qry); $rs_tmp->bindValue(":date", '2038/01/15'); $rs_tmp->execute(); $row_tmp = $rs_tmp->fetch(PDO::FETCH_ASSOC); echo $row_tmp['next_date']; 

    Не может быть эффективным способом, но он работает.

    Существует еще один способ предотвратить это, я не буду вдаваться в подробности, но это действительно простая математика, упрощая проблему, вы можете на самом деле иметь 4-разрядное число в mysql и использовать средний int. И все же сможете опубликовать его как правильное время, даже в 2038 году.