Вопрос появился, когда занялся написания статистики и заказов в одном сайте. Возникла проблема с датами. В БД все даты хранятся в юниксе. Думаю секрета нет, что ЮНИКС время имеет крайний срок 2038 год (исходя из своей 32-bit'ной структуре). Вот нужно работать с датами выше 2038 года (уже не за горами). Какие есть пути решения. Никаких библиотечек или модулей для PHP 5.4 я не нашел (плохо искал?). Подскажите, кто знает как побороть эту проблему уже сейчас.
Да бросьте... Делаете из мухи слона. Неужели вы думаете, что разработчики не знают об этом баге и не найдут выход из положения? Мускулу всего 19 лет! Получается, что времени (23-24 года) на дебаг больше, чем возраст самого MySQL.
Вспомнилось просто в тему Код (PHP): function isLeapYear($year) { //return (($year % 4 == 0 && $year %100 != 0) || $year % 400 == 0); // да ну, 2000 год прошел, а до 2100 эта система явно не доработает return ($year%4 == 0); }
Лопатить много полей нужно + весь код шерстить и перепиливать со стороны пхп, не вариант. Так в том то и дело уже сейчас потребовалось хранить такую дату (большую 2038 года, в случае с заказами). Например здесь http://www.cy-pr.com/tools/time/ юникс уже обучан понимать и работать с такими большими датами. Значит както сделали дату 64 битной. Либо может ведут подсчет не через пхп, а через питон, например?
Например, строка красиво умирает при достижении верхнего предела Код (PHP): <span class="syntaxdefault"><br /></span><span class="syntaxcomment">//продление срока "жизни" пользователя на 1 год<br /></span><span class="syntaxdefault">$user</span><span class="syntaxkeyword">-></span><span class="syntaxdefault">date_end </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">strtotime</span><span class="syntaxkeyword">(</span><span class="syntaxstring">"+1 year"</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">$user</span><span class="syntaxkeyword">-></span><span class="syntaxdefault">date_end</span><span class="syntaxkeyword">);</span><span class="syntaxdefault"> <br /></span> И как нам это поможет в решении проблемы?
она не 32-битная, а целочисленная. В моде давно 64 бит, следовательно проблема откладывается на несколько тысячилетей.
мой воркэраунд: Код (PHP): <?php /* // cannot exceed 2038 $d = strtotime('2030-01-01'); for ($i = 0; $i < 10; ++$i) { $d = strtotime('+1 year', $d); echo $d.' == '.date('Y-m-d', $d)."\n"; } */ $d = new DateTime('2030-01-01'); $year = new DateInterval('P0001-00-00T00:00:00'); for ($i = 0; $i < 10; ++$i) { $d->add($year); echo $d->format('Y-m-d')."\n"; } Код (Text): 2031-01-01 2032-01-01 2033-01-01 2034-01-01 2035-01-01 2036-01-01 2037-01-01 2038-01-01 2039-01-01 2040-01-01
Так все могут. Да вот всё и код, и ДБ на юникс-времени завязан. А с ним что нибудь сделать в данный момент времени можно? Чтобы не перепиливать все.
В БД MySQL существуют несколько типов для хранения даты, времени timestamp - по сути UNIX-время datetime - по сути - строка (0000-00-00 00:00:00 -> 9999-99-99 23:59:59) Когда использовать timestamp а когда datetime - решайте сами. Есть небольшие нюансы в различии (например учёт временного пояса), но в целом, для ваших целей, подходит любое Добавлено спустя 4 минуты 31 секунду: http://habrahabr.ru/post/61391/
ты только главного не написал — что mysql тип datetime позволяет хранить даты > 2038г, что и требуется топикстартеру
а на стороне PHP придется работать через DateTime. Всем спасибо. PS - Все же надеялся обойтись каким-нибудь фиксом для юникс-времени, но видимо такого решения пока нет
можешь взять паузу на пару лет, наверняка в ближайших версиях это поправят ))) реально целое число на 64бит платформе уже сейчас 64 бита. жаль, что библиотечные функции отстают.
Глядя в этот открытый баг: http://bugs.mysql.com/bug.php?id=12654 и опираясь на личный опыт у меня рождается вопрос: а почему вы еще пользуетесь timestamp? Время до 2038 года есть, переезжайте, не ждите что кто-то будет его чинить, скорее всего объявят как deprecated и все. конвертация базы: Код (Text): ALTER TABLE `myTable` CHANGE `myTimestamp` `temp_myTimestamp` int(11) NOT NULL; ALTER TABLE `myTable` ADD `myTimestamp` DATETIME NOT NULL; UPDATE `myTable` SET `myTimestamp` = FROM_UNIXTIME(temp_myTimestamp); ALTER TABLE `myTable` DROP `temp_myTimestamp`
оказывается беспокоиться ненужно, если нормальное железо и нужная сборка php On 32-bit hardware: $ php -r 'echo PHP_INT_MAX;' 2147483647 On 64-bit hardware: $ php -r 'echo PHP_INT_MAX;' 9223372036854775807
функции работы с unixtime по прежнему используют 32битнный формат целого. сейчас у меня нет возможности проврить, если ты это сделаешь и расскажешь — общество будет благодарно!
а я хочу заострить внимание, что дело не всегда в PHP и архитектуре сборки: sql/mysql_priv.h: Код (Text): /* Time handling defaults */ #define TIMESTAMP_MAX_YEAR 2038 #define YY_PART_YEAR 70 #define TIMESTAMP_MIN_YEAR (1900 + YY_PART_YEAR - 1) #define TIMESTAMP_MAX_VALUE 2145916799 #define TIMESTAMP_MIN_VALUE 1 #define PRECISION_FOR_DOUBLE 53 #define PRECISION_FOR_FLOAT 24
Все нормально, если библиотечки от php 64 Код (PHP): echo $ut = mktime(0, 0, 0, 1, 1, 2111); // 4449499200 echo date("c",$ut); // 2111-01-01T00:00:00+04:00 echo strtotime("2345-01-01 +1 year"); // 11865384000
1. ты не меня процитировал, откуда там мой никнейм? ))) 2. ок. у тебя значит успех. а у меня есть инсталированный на винде php 5.4.21 64bit, у которого всё по старому. наверное потому что сборка "неофициальная"
1. мой косяк, хотя даже по понял как он получился 2. какие ddl файлы с припиской в имени 32 или 64 лежат в папке php ? Сам на Debian сижу, не знаю таких проблем. )
Мужики, не спорьте уже, кусок выше из MySQL, так что без разницы как и чего у вас с php. сказано #define TIMESTAMP_MAX_VALUE 2145916799 и #define TIMESTAMP_MAX_YEAR 2038 значит так и будет.
разве кто-то спорит! hren2, что ты пытаешся выяснить, какие еще ddl? есть достоверные способы проверить битность программы )))