Работа с временными зонами в PHP
Как только проект перестает быть завязан на ограниченное количество потребителей и растет география его применения, встает вопрос о применении временных зон. Когда я работал в одной известной интернет компании внедрение в работу временных зон (как в интерфейс отображения статистики, так и в программу анализа) было достаточно серьезным шагом.
- Проблемы временных зон
- Проблемы перевода времени
- Другие проблемы временных зон и «перевода стрелок»
- Проблемы в наименовании временных зон
- Проблемы в представлении даты и времени
- Функции в php 4 и php 5 для работы с временем и датами
- Ограничения работы с датами
- Улучшения работы с датами в php 5.1 и выше
- Форматы данных в php 5.1 и выше
- Поддержка временных зон в php 5.1 и выше
- Поддержка временных зон. Как использовать?
- Изменение информации по временным зонам
- Разбор дат (прошлое)
- Разбор дат (будущее)
- Разбор строки, используя функцию date_parse
- Формат дат
- Локали в php6
- Обновление даты и времени
- Изменение даты и времени
- Использование временных зон
- Временная зона по умолчанию
- Использование временных зон. Объект временная зона
- Использование временных зон. Изменение временной зоны
- Таблицы перевода времени
- Аббревиатуры и идентификаторы
- Перевод стрелок. Когда будет следующий?
- Когда появится данная функциональность
- Большинство мест на земле имеют часовое смещение
- Некоторые места имеют получасовое или пятнадцати-минутное временное смещение
- В некоторых местах временная зона меняется в течении года
- Множество стран переводит время дабы увеличить продолжительность светлой части суток
- Это делают не во всех странах
- Перевод часов происходит в разное время
- Существует большое количество исключений
- В Австралии зоны строго вертикальные
- В Бразилии дата, когда переводят срелки, меняется каждый год
- На остров Lord Howe (Австралия) переводят стрелки только на почаса
- Непал переводит стрелки на 15 минут
- Одно именование может означать разные временные зоны:
Например:PST — Pacific Standart Time и Pakistan Standart Time
EST — Easten Standart Time (США), Easten Standart Time (Австралия) и Easten Brazil Standart Time - Одна зона может иметь несколько наименований
- Двусмысленность
06/08/04
6 Августа 2004 года
8 Июня 2004 года
4 Августа 2006 - Нечитаемость
20040425010541
25 Апреля 2004 года 01:05:41 - Другие «магические» форматы
third saturday
2004-03-10 16:33:17.11403+1
2001-11-29T13:20:01.123-05:00
23:41:00.0Z
04:05:07.789 +0930
1999.238
- checkdate — Проверяет правильность даты по грегорианскому календарю
- date(gmdate) — Форматирует системную дату/время (по Гринвичу)
- getdate — Возвращает информацию о дате/времени
- gettimeofday — Возвращает текущее время
- localtime — Возвращает системное время
- mktime(gmmktime) — Возвращает метку времени для заданной даты (по Гринвичу)
- strftime(gmstrftime) — Форматирует дату/время с учетом текущей локали (по Гринвичу)
- strtotime — Преобразует текстовое представление даты на английском языке в метку времени Unix
- Использование Unix-таймстампа в качестве базы (количество секунд, прошедшее с 1 января 1970 года по Гринвичу)
- Таймстамп представляется ввиде 32-битного целого, что ограничивает использование данного представления диапазоном 1902-2038 годами
- На многих операционных системах данный тип может быть только положительным, ограничение диапазона 1970-2038
- strtotime — достачно сложная функция, реализация которой подвержена большим количеством ошибок
- Нет вариантов корректной работы с временными зонами
- Некоторые функции являются зависимыми от операционной системы
- Использование 64-битного типа для хранения даты. Теперь граница интервала использования данного типа 4 Декабря 292277026596 год
- Функция strtorime была переписана
- Больше нет зависимости в реализации от операционной системы
- Полная поддержка временных зон, перевода часов и модификаторов дат
- Новый формат модификаторов временных зон
- Более продвинутые функции для работы с датами
- Встроенная база на 551 временную зону
- Нет зависимости от аббревиатуры временной зоны
- Названия временных зон имеют формат — Continent/Location или Continent/Location/Sublocation
- Каждая временная зона идентифицируется городом с наибольшим населением на данной территории
- Зоны разделены на 10 больших групп: Африка, Америка, Антарктика, Арктика, Азия, Европа, Индия, Тихий океан
- Существует также группа Другие, состоящая из вышедших из употребления названий и служащая для обеспечения обратной совместимости
- Больше информации по аббревиатурам временных зон по указанному адресу
- Обновления информации по временным зонам происходят около 20 раз в год
- Большинство обновлений происходят неожиданно
- Чтобы не потерять актуальность, релизы php должны быть достаточно часты
- Расширение pecl, которое исправляет данные недостатки, называется timezonedb (pecl install timezonedb)
Возвращаемое значение представляет собой 32-битное целое
Разбор дат (будущее)
Разбор строки, содержащей информацию о дате и времени, используя функцию date_create
«$ts=date_create(«1978-12-22 09:15:50»);»
В качестве альтернативы можно сосздать объект типа DateTime
Эти функции уже не используют 32-битное целое, они возвращают объект класса DateTime, который является оберткой над 64-битным целым, для доступа к которому следует использовать следующую конструкцию
date_default_timezone_set(«Europe/Oslo»);
$ts=date_create(«1979-12-31 09:15»);
echo date_format($ts,«D Y-m-d H:i:s -\I\S\O \W/\Y: W/o»);
Все модификаторы форматов, поддерживаемые функцией date, поддерживаются тоже
Предопределенные форматы:
date_default_timezone_set(«Europe/Oslo»);
$ts=date_create(«December 22nd, 2005 15:41»);
echo date_format($ts, DATE_ISO8601);
echo date_format($ts, DateTime::RFC1036);
echo date_format($ts, DATE_RSS);
date_default_timezone_set(«Europe/Oslo»);
$ts=date_create(«December 22nd, 2005 15:41»);
$locales=array(‘en_US’,’fr_CA’,’nb_NO’,’ru_RU’,’ar_SA’,’ja_JP’);
foreach($locales as $locale)
locale_set_default($locale);
echo date_format_locale($ts,DATE_RFC2822).»\n»;
>
$date=new DateTime(‘now’);
echo $date->format(DateTime::ISO8601).»\n»;
$date->setTime(15,0,7);
echo $date->format(DateTime::ISO8601).»\n»;
$date->setDate(2006,12,22);
echo $date->format(DateTime::ISO8601).»\n»;
$date->setIsoDate(2006,45,2);
echo $date->format(DateTime::ISO8601).»\n»;
date_default_timezone_set(«Europe/Oslo»);
$date=new DateTime(‘now’);
echo $ts->format(DATE_RFC2822).»\n»;
$ts->modify(«+2 days»);
echo $ts->format(DATE_RFC2822).»\n»;
$ts->modify(«fifth month»);
echo $ts->format(DATE_RFC2822).»\n»;
$ts->modify(«Friday +3 weeks»);
echo $ts->format(DATE_RFC2822).»\n»;
$ts->modify(«next friday»);
echo $ts->format(DATE_RFC2822).»\n»;
Использование временных зон
Установка сокращенного названия временной зоны при разборе даты
Использование аббревиатур временных зон признано устаревшим, необходимо установить временную зону по умолчанию или полный идентификатор временной зоны
date_default_timezone_set(«Europe/Oslo»);
$ts=date_create(«1978-12-22 09:15»);
echo $ts->format(‘e’);
- значением установленным функцией date_default_timezone_set()
- переменной окружения TZ
- значением date.timezone в php.ini
- системным отображением сокращения имени временной зоны
Использование временной зоны в качестве аргумента функций не перекрывает временную зону, указанную в разбираемой строке
$tz=new DateTimeZone(‘Pacific/Honolulu’);
$ts1=new DateTime(‘1978-12-22 09:15 CEST’,$tz);
$ts2=new DateTime(‘1978-12-22 09:15 Europe/Amsterdam’,$tz);
echo $ts2->format(DateTime::RFC2822);
$tz=timezone_open(‘Asia/Singapore’);
echo timezone_name_get($tz);
$tz=timezone_open(‘CEST’);
echo timezone_name_get($tz);
$tz=new DateTimeZone(»Europe/Amsterdam»);
$d=new DateTime(«2005-01-22 09:15»);
echo $tz->getOffset($d);
$d->modify(«+6 months»);
echo $tz->getOffset($d);
Использование временных зон. Изменение временной зоны
Использование временной зоны при разборе строкового представления
$tz1=timezone_open(‘Pacisic/Honolulu’);
$tz2=timezone_open(‘Europe/Amsterdam’);
$tz3=timezone_open(‘Australia/Melbourne’);
$ts=date_create(«1978-12-22 09:15»,$tz1);
echo $ts->getTimezone()->getName().’:’.$ts->format(DATE_RFC822).»\n»;
$ts->setTimezone($tz2);
echo $ts->getTimezone()->getName().’:’.$ts->format(DATE_RFC822).»\n»;
$ts->setTimezone($tz3);
echo $ts->getTimezone()->getName().’:’.$ts->format(DATE_RFC822).»\n»;
$tz=timezone_open(‘Europe/Amsterdam’);
$trs=timezone_transitions_get($tz); // или $trs=$tz->getTransitions();
foreach($trs as $ts)
printf(«%20s %7d %d %s\n»,$tr[‘time’],$tr[‘offset’],$tr[‘isdst’],$tr[‘abbr’]);
$ids = timezone_identifiers_list();
echo «Number of identifiers: ».count($ids).»\n»;
echo implode(«, «, array_slice($ids, 0, 5)).’. ‘.implode(«, «, array_slice($ids, -5));
$abbrs = timezone_abbreviations_list();
foreach ($abbrs as $abbr => $ids)
foreach ($ids as $id)
printf(«%-6s %6d %d %s\n», strtoupper($abbr),$id[‘offset’],$id[‘dst’], $id[‘timezone_id’]);
date_default_timezone_set(«America/New_york»);
$tz = new DateTimeZone(«America/New_york»);
foreach (timezone_transitions_get($tz) as $tr)
if ($tr[‘ts’] > time()) break;
$d = new DateTime( «@» );
printf(«The timezone %s switches to %s on %s.\nThe new GMT offset will be: %d (%s)\n», $tz->getName(), $tr[‘isdst’]? «DST»: «standard time», $d->format(‘d M Y @ H:i T’), $tr[‘offset’], $tr[‘abbr’]);
Когда появится данная функциональность
В php 5.1 необходимо скомпилировать, используя флаг CFLAGS=-DEXPERIMENTAL_DATE_SUPPORT=1
В php 5.2 и выше по умолчанию
Как управлять часовыми поясами в PHP
Изучите основы использования часовых поясов в PHP и как сделать лучший выбор из набора функций предлагаемых PHP.
В этой краткой статье мы объясним основы использования часовых поясов в PHP. Работы с часовыми поясами — важный навык для каждого программиста, работающего с веб-приложениями. Поскольку на протяжении многих лет PHP в основном использовался для веб-приложений, он имеет довольно простую, но всестороннюю поддержку часовых поясов.
Часовые пояса и PHP
Часовые пояса поддерживаются в PHP с версии 4. Но то, что начиналось как базовая реализация функции date_default_timezone_set() , быстро развилось в PHP 5 и 7 с введением классов DateTimeZone и DateTimeZoneImmutable .
DateTimeZoneImmutable — подкласс DateTimeZone позволяющий создавать часовые пояса, невосприимчивые к изменениям. Эта функция может быть очень полезна в ситуациях, когда нужно быть уверенным, что часовой пояс никогда не изменится.
Функция date_default_timezone_set() устанавливает часовой пояс по умолчанию, используемый всеми функциями времени/даты в данном скрипте. Эта функция позволяет настроить часовой пояс, но имеет очень небольшую степень детализации, что вынуждает использовать один и тот же часовой пояс в течении выполнения скрипта.
Классы DateTimeZone и DateTimeZoneImmutable привнесли больше контроля и гибкости в работу с часовыми поясами. Теперь мы можем получить доступ ко всем видам информации о часовом поясе, а также к нескольким экземплярам разных часовых поясов в одном скрипте.
Использование в PHP часовых поясов
Использование date_default_timezone_set()
date_default_timezone_set('Europe/Moscow');
Часовые пояса в методе date_default_timezone_set() всегда определяются в форматах Континент/город или Континент/Страна/Город . Полный список часовых поясов поддерживаемых в PHP, вы можете найти по ссылке
Это установит часовой пояс в часовой пояс переданный в качестве аргумента. После того как мы установили часовой пояс, можно использовать такие функции, как date_default_timezone_get() или любые другие функции, связанные со временем, такие как date() , для доступа к информации о новом часовом поясе.
Использование класса DateTimeZone
Лучшим способом использования часовых поясов в PHP является использование класса DateTimeZone . Это означает, что у нас есть доступ к большему количеству функций для доступа к информации и управления часовыми поясами, и мы можем создавать несколько экземпляров класса, что позволяет работать с несколькими часовыми поясами:
$timezone = new DateTimeZone('Asia/Novosibirsk');
$datetime = new DateTime($date, $timezone);
echo $datetime->format('Y-m-d H:i:s');
В этом примере мы создаём новый объект DateTimeZone и передаём его новому экземпляру DateTime . Затем объект DateTime будет использовать информацию из объекта DateTimeZone . Наконец, мы используем функцию format() для вывода даты в предпочтительном формате.
Заключение
Как вы видели, работать с часовыми поясами в PHP довольно просто. Убедитесь, что выбрали лучший способ для своего варианта использования, и PHP вам поможет!