За последние 24 часа нас посетили 21042 программиста и 1108 роботов. Сейчас ищут 445 программистов ...

Юникс время и 2038 год

Тема в разделе "Прочие вопросы по PHP", создана пользователем hren2, 6 авг 2014.

  1. hren2

    hren2 Активный пользователь

    С нами с:
    27 июн 2011
    Сообщения:
    41
    Симпатии:
    0
    Вопрос появился, когда занялся написания статистики и заказов в одном сайте.
    Возникла проблема с датами. В БД все даты хранятся в юниксе. Думаю секрета нет, что ЮНИКС время имеет крайний срок 2038 год (исходя из своей 32-bit'ной структуре).
    Вот нужно работать с датами выше 2038 года (уже не за горами). Какие есть пути решения.
    Никаких библиотечек или модулей для PHP 5.4 я не нашел (плохо искал?).
    Подскажите, кто знает как побороть эту проблему уже сейчас.
     
  2. topas

    topas Активный пользователь

    С нами с:
    16 авг 2006
    Сообщения:
    2.258
    Симпатии:
    36
    > В БД все даты хранятся в юниксе
    храните в datetime
     
  3. Deonis

    Deonis Старожил

    С нами с:
    15 фев 2013
    Сообщения:
    1.521
    Симпатии:
    504
    Да бросьте... Делаете из мухи слона. Неужели вы думаете, что разработчики не знают об этом баге и не найдут выход из положения? Мускулу всего 19 лет! Получается, что времени (23-24 года) на дебаг больше, чем возраст самого MySQL.
     
  4. Хыиуду

    Хыиуду Активный пользователь

    С нами с:
    3 июн 2014
    Сообщения:
    618
    Симпатии:
    5
    Вспомнилось просто в тему
    Код (PHP):
    1. function isLeapYear($year) {
    2.     //return (($year % 4 == 0 && $year %100 != 0) || $year % 400 == 0);
    3.     // да ну, 2000 год прошел, а до 2100 эта система явно не доработает
    4.     return ($year%4 == 0);
    5. } 
     
  5. hren2

    hren2 Активный пользователь

    С нами с:
    27 июн 2011
    Сообщения:
    41
    Симпатии:
    0
    Лопатить много полей нужно + весь код шерстить и перепиливать со стороны пхп, не вариант.

    ;)

    Так в том то и дело уже сейчас потребовалось хранить такую дату (большую 2038 года, в случае с заказами).
    Например здесь http://www.cy-pr.com/tools/time/ юникс уже обучан понимать и работать с такими большими датами. Значит както сделали дату 64 битной. Либо может ведут подсчет не через пхп, а через питон, например?
     
  6. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.068
    Симпатии:
    1.231
    Адрес:
    там-сям
    продемонстрируй проблему на реальном примере.
     
  7. hren2

    hren2 Активный пользователь

    С нами с:
    27 июн 2011
    Сообщения:
    41
    Симпатии:
    0
    Например, строка красиво умирает при достижении верхнего предела
    Код (PHP):
    1. <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">=&nbsp;</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>
    И как нам это поможет в решении проблемы?
     
  8. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.553
    Симпатии:
    631
    она не 32-битная, а целочисленная. В моде давно 64 бит, следовательно проблема откладывается на несколько тысячилетей.
     
  9. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.068
    Симпатии:
    1.231
    Адрес:
    там-сям
    мой воркэраунд:
    Код (PHP):
    1. <?php
    2. /*
    3. // cannot exceed 2038 
    4. $d = strtotime('2030-01-01');
    5. for ($i = 0; $i < 10; ++$i) {
    6.     $d = strtotime('+1 year', $d); 
    7.     echo $d.' == '.date('Y-m-d', $d)."\n";
    8. }
    9. */
    10. $d = new DateTime('2030-01-01');
    11. $year = new DateInterval('P0001-00-00T00:00:00');
    12. for ($i = 0; $i < 10; ++$i) {
    13.     $d->add($year); 
    14.     echo $d->format('Y-m-d')."\n";
    15. }
    Код (Text):
    1. 2031-01-01
    2. 2032-01-01
    3. 2033-01-01
    4. 2034-01-01
    5. 2035-01-01
    6. 2036-01-01
    7. 2037-01-01
    8. 2038-01-01
    9. 2039-01-01
    10. 2040-01-01
     
  10. hren2

    hren2 Активный пользователь

    С нами с:
    27 июн 2011
    Сообщения:
    41
    Симпатии:
    0
    Так все могут. Да вот всё и код, и ДБ на юникс-времени завязан. А с ним что нибудь сделать в данный момент времени можно? Чтобы не перепиливать все.
     
  11. topas

    topas Активный пользователь

    С нами с:
    16 авг 2006
    Сообщения:
    2.258
    Симпатии:
    36
    В БД 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/
     
  12. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.068
    Симпатии:
    1.231
    Адрес:
    там-сям
    ты только главного не написал — что mysql тип datetime позволяет хранить даты > 2038г, что и требуется топикстартеру
     
  13. hren2

    hren2 Активный пользователь

    С нами с:
    27 июн 2011
    Сообщения:
    41
    Симпатии:
    0
    а на стороне PHP придется работать через DateTime.
    Всем спасибо.
    PS - Все же надеялся обойтись каким-нибудь фиксом для юникс-времени, но видимо такого решения пока нет
     
  14. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.068
    Симпатии:
    1.231
    Адрес:
    там-сям
    можешь взять паузу на пару лет, наверняка в ближайших версиях это поправят )))
    реально целое число на 64бит платформе уже сейчас 64 бита. жаль, что библиотечные функции отстают.
     
  15. Ke1eth

    Ke1eth Активный пользователь

    С нами с:
    16 мар 2012
    Сообщения:
    1.073
    Симпатии:
    11
    Адрес:
    заблудилса
    Глядя в этот открытый баг: http://bugs.mysql.com/bug.php?id=12654 и опираясь на личный опыт у меня рождается вопрос: а почему вы еще пользуетесь timestamp?
    :)
    Время до 2038 года есть, переезжайте, не ждите что кто-то будет его чинить, скорее всего объявят как deprecated и все.

    конвертация базы:
    Код (Text):
    1.  
    2. ALTER TABLE `myTable` CHANGE `myTimestamp` `temp_myTimestamp` int(11) NOT NULL;
    3.  
    4. ALTER TABLE `myTable` ADD `myTimestamp` DATETIME NOT NULL;
    5.  
    6. UPDATE `myTable` SET `myTimestamp` = FROM_UNIXTIME(temp_myTimestamp);
    7.  
    8. ALTER TABLE `myTable` DROP `temp_myTimestamp`
     
  16. hren2

    hren2 Активный пользователь

    С нами с:
    27 июн 2011
    Сообщения:
    41
    Симпатии:
    0
    оказывается беспокоиться ненужно, если нормальное железо и нужная сборка php

    On 32-bit hardware:

    $ php -r 'echo PHP_INT_MAX;'
    2147483647

    On 64-bit hardware:

    $ php -r 'echo PHP_INT_MAX;'
    9223372036854775807
     
  17. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.553
    Симпатии:
    631
    Эврика!
     
  18. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.068
    Симпатии:
    1.231
    Адрес:
    там-сям
    функции работы с unixtime по прежнему используют 32битнный формат целого.

    сейчас у меня нет возможности проврить, если ты это сделаешь и расскажешь — общество будет благодарно!
     
  19. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    Да пофик. Через десять лет не будет вообще ничего 32 бит. Центось седьмая вышла только 64 версия.
     
  20. Ke1eth

    Ke1eth Активный пользователь

    С нами с:
    16 мар 2012
    Сообщения:
    1.073
    Симпатии:
    11
    Адрес:
    заблудилса
    а я хочу заострить внимание, что дело не всегда в PHP и архитектуре сборки:
    sql/mysql_priv.h:
    Код (Text):
    1.  
    2. /* Time handling defaults */
    3. #define TIMESTAMP_MAX_YEAR 2038
    4. #define YY_PART_YEAR       70
    5. #define TIMESTAMP_MIN_YEAR (1900 + YY_PART_YEAR - 1)
    6. #define TIMESTAMP_MAX_VALUE 2145916799
    7. #define TIMESTAMP_MIN_VALUE 1
    8. #define PRECISION_FOR_DOUBLE 53
    9. #define PRECISION_FOR_FLOAT  24
     
  21. hren2

    hren2 Активный пользователь

    С нами с:
    27 июн 2011
    Сообщения:
    41
    Симпатии:
    0
    Все нормально, если библиотечки от php 64
    Код (PHP):
    1.    echo $ut = mktime(0, 0, 0, 1, 1, 2111); // 4449499200
    2.    echo date("c",$ut); // 2111-01-01T00:00:00+04:00
    3.    echo strtotime("2345-01-01 +1 year"); // 11865384000 
    4.  
     
  22. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.068
    Симпатии:
    1.231
    Адрес:
    там-сям
    1. ты не меня процитировал, откуда там мой никнейм? )))
    2. ок. у тебя значит успех. а у меня есть инсталированный на винде php 5.4.21 64bit, у которого всё по старому. наверное потому что сборка "неофициальная"
     
  23. hren2

    hren2 Активный пользователь

    С нами с:
    27 июн 2011
    Сообщения:
    41
    Симпатии:
    0
    1. мой косяк, хотя даже по понял как он получился
    2. какие ddl файлы с припиской в имени 32 или 64 лежат в папке php ?

    Сам на Debian сижу, не знаю таких проблем. )
     
  24. Ke1eth

    Ke1eth Активный пользователь

    С нами с:
    16 мар 2012
    Сообщения:
    1.073
    Симпатии:
    11
    Адрес:
    заблудилса
    Мужики, не спорьте уже, кусок выше из MySQL, так что без разницы как и чего у вас с php.
    сказано #define TIMESTAMP_MAX_VALUE 2145916799 и #define TIMESTAMP_MAX_YEAR 2038 значит так и будет.
     
  25. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.068
    Симпатии:
    1.231
    Адрес:
    там-сям
    разве кто-то спорит! hren2, что ты пытаешся выяснить, какие еще ddl? есть достоверные способы проверить битность программы )))