[Из песочницы] Перевод часов в России 26 октября и icu4c

Многие уже поставили обновление tzdata на свои любимые дистрибутивы и с нетерпением ждут конца света 26 октября 2014 года, когда можно будет в 2 часа ночи ощутить себя на все 3.Но всё ли в порядке, если вы пишите на PHP и используете Symfony Forms, или просто php-intl?! Мой ответ — нет.Проверить себя вы можете просто:

$dateIn = '27.10.2014'; $tz = 'Europe/Moscow'; date_default_timezone_set ($tz); $intlDateFormatter = new \IntlDateFormatter ('ru_RU', 2, -1, $tz, 1, 'dd.MM.yyyy'); $timestamp = $intlDateFormatter→parse ($dateIn);

var_dump ($intlDateFormatter→format ($timestamp)); var_dump (date ('d.m.Y', $timestamp)); На debian wheezy, centos после обновления tzdata этот код выведет: string (16) »27.10.2014» string (16) »26.10.2014» Это происходит потому, что у библиотеки icu своя база данных временных зон (это популярное занятие, например, также делает php, java, chrome и вагон другого софта) и при пересчете даты в unixtimestamp она отнимает 4 часа, а php функция date прибавляет только 3, и если поле у вас только для ввода даты, то после отбрасывания времени вы получите на день меньше от введенной даты.Ситуацию усугубляет еще и то, что данные эти хранятся в виде библиотеки libicudata, поэтому готовьтесь собирать icu из исходников.

Все действия далее выполняются на отдельной VM под управлением CentOS 6.5 + remi + libicu-last.

По версии пакета определяем версию icu — 50.1.2 (исходники на сайте icu), также отсюда скачиваем все *.res файлы, где (в ссылке)2014i — версия tzdata;44 — версия libicu (44 и все что больше); le — little endian (дада если у вас mips arm и т.п. вам может потребоваться другой набор ресурсов).

tar -zxf icu4c-50_1_2-src.tgz cd icu/source mkdir bin ./configure

# собираем утилиту pkgdata cd tools/pkgdata/ make cd …/…/

# теперь обновим файл данных cd data/in/

# копируем скаченные ранее файлы в эту папку и добавляем их в файл данных …/…/bin/pkgdata -a zoneinfo64.res icudt50l.dat …/…/bin/pkgdata -a metaZones.res icudt50l.dat …/…/bin/pkgdata -a timezoneTypes.res icudt50l.dat …/…/bin/pkgdata -a windowsZones.res icudt50l.dat

# после чего запускаем сборку cd …/…/ make В принципе, на этом можно остановится и после сборки заменить в системе библиотеку из /usr/lib64/ на новую версию ./lib/libicudata.so.50.1.2.Я же собрал пакет:

yum install rpmrebuild rpmrebuild -e -p --notest-install libicu-last-50.1.2–10.el6.remi.x86_64.rpm По строчке вида BuildRoot: /root/.tmp/rpmrebuild.42406/work/root определяем, где находятся распакованные файлы пакета и заменяем libicudata на свежую версию, получившийся пакет (rpmbuild напишет полный путь после сборки) можно установить с указанием ключа --force, так как мы не меняли его версию.Спасибо за внимание!

© Habrahabr.ru