PHP & mySQL: 2038 год ошибка: что это такое? Как ее решить?
Я думал использовать метку времени для хранения даты+времени, но я прочитал, что на ней есть ограничение 2038 года. Вместо того, чтобы задавать свой вопрос навалом, я предпочел разбить его на мелкие части, чтобы начинающим пользователям было легко понять. Так что мой вопрос(ы):
- что именно является проблемой 2038 года?
- почему это происходит, и что происходит, когда это происходит?
- как мы ее решаем?
- есть ли возможность альтернативы его использованию, которые не создают подобной проблемы?
- что мы можем сделать с существующими приложениями, которые используют метку времени, чтобы избежать так называемой проблемы, когда это действительно происходит?
спасибо заранее.
6 ответов:
я отметил это как Вики сообщества, так что не стесняйтесь редактировать на досуге.
что именно является проблемой 2038 года?
"проблема 2038 года (также известная как ошибка тысячелетия Unix, 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, но отметка времени имеет только диапазон 1970-2038. Если в вашей системе хранятся даты рождения, будущие даты вперед (например, 30-летние ипотечные кредиты) или аналогичные, вы уже столкнетесь с этой ошибкой. Опять же, не используйте метку времени, если это будет проблемой.
что мы можем сделать, чтобы существующие приложения, которые используют метку времени, чтобы избежать так называемой проблемы, когда это действительно происходит?
несколько 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`
ресурсы
при использовании временных меток UNIX для хранения дат вы фактически используете 32-битные целые числа, которые сохраняют количество секунд с 1970-01-01; см. Unix Time
это 32-битное число переполнится в 2038 году. Это проблема 2038.
Чтобы решить эту проблему, вы не должны использовать 32-битную метку времени UNIX для хранения ваших дат - что означает, что при использовании MySQL вы не должны использоватьTIMESTAMP, аDATETIME(см. 10.3.1. Этот Типы DATETIME, DATE и TIMESTAMP):The
DATETIMEтип используется, когда вы необходимые значения, содержащие как дату, так и информация о времени. Поддерживаемый диапазон это'1000-01-01 00:00:00'to'9999-12-31 23:59:59'.The
TIMESTAMPтип данных имеет ряд из'1970-01-01 00:00:01'UTC to'2038-01-19 03:14:07'UTC.
Элемент (вероятно) лучшее, что вы можете сделать, чтобы ваше приложение, чтобы избежать/исправить эту проблему, чтобы не использоватьTIMESTAMP, аDATETIMEдля столбцов, которые должны содержать даты, которые не находятся между 1970 и 2038 годами.одна маленькая заметка, хотя : есть очень высокий, вероятно,(статистически говоря) что ваше приложение будет переписано довольно много раз до 2038 ^^ так что, возможно, если вам не придется иметь дело с датами в будущем, вам не придется заботиться об этой проблеме с текущей версией вашего приложения...
быстрый поиск в Google сделает трюк: проблема 2038 года
- проблема 2038 года (также известная как ошибка тысячелетия Unix, Y2K38 по аналогии с проблемой Y2K) может привести к сбою некоторых компьютерных программ до или в 2038 году
- проблема затрагивает все программное обеспечение и системы, которые хранят системное время в виде 32-разрядного целого числа со знаком и интерпретируют это число как количество секунд с 00:00:00 UTC 1 января 1970 года. Позднее время это может быть представлено таким образом, 03:14:07 UTC во вторник, 19 января 2038 года. Времена после этого момента будут "обертываться" и храниться внутри как отрицательное число, которое эти системы будут интерпретировать как дату в 1901 году, а не 2038
- нет простого решения этой проблемы для существующих комбинаций ЦП / ОС, существующих файловых систем или существующих форматов двоичных данных
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-битные ints. Или для баз данных используйте альтернативный формат метки времени (например, для MySQL используйте DATETIME)
4) смотрите 3!
5) см. 4!!! ;)
Bros, если вам нужно использовать PHP для отображения временных меток, это лучшее решение PHP без изменения формата UNIX_TIMESTAMP.
используйте функцию custom_date (). Внутри него, использовать тип datetime. вот решение DateTime.
пока у вас есть неподписанный BIGINT(8) в качестве временных меток в базе данных. Пока у вас есть PHP 5.2.0 ++
поскольку я не хотел ничего обновлять, я попросил мой бэкэнд (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'];не может быть эффективным способом, но это работает.
Comments