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