Работа с временными зонами в 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 и выше по умолчанию
date_default_timezone_set
date_default_timezone_set() устанавливает часовой пояс по умолчанию для всех функций даты/времени в скрипте.
Вместо использования этой функции, вы можете воспользоваться INI-настройкой date.timezone для установки часового пояса по умолчанию.
Список параметров
Идентификатор часового пояса, например, UTC , Africa/Lagos , Asia/Hong_Kong или Europe/Lisbon . Список допустимых идентификаторов часовых поясов можно найти в разделе Список поддерживаемых часовых поясов.
Возвращаемые значения
Функция возвращает false , если timezoneId имеет неверное значение, в остальных случаях true .
Примеры
Пример #1 Получение часового пояса по умолчанию
if ( strcmp ( $script_tz , ini_get ( ‘date.timezone’ ))) echo ‘Часовой пояс скрипта отличается от заданного в INI-файле.’ ;
> else echo ‘Часовой пояс скрипта и настройки INI-файла совпадают.’ ;
>
?>
Смотрите также
- date_default_timezone_get() — Возвращает часовой пояс, используемый по умолчанию всеми функциями даты/времени в скрипте
- Список поддерживаемых часовых поясов
User Contributed Notes
- Функции даты и времени
- checkdate
- date_add
- date_create_from_format
- date_create_immutable_from_format
- date_create_immutable
- date_create
- date_date_set
- date_default_timezone_get
- date_default_timezone_set
- date_diff
- date_format
- date_get_last_errors
- date_interval_create_from_date_string
- date_interval_format
- date_isodate_set
- date_modify
- date_offset_get
- date_parse_from_format
- date_parse
- date_sub
- date_sun_info
- date_sunrise
- date_sunset
- date_time_set
- date_timestamp_get
- date_timestamp_set
- date_timezone_get
- date_timezone_set
- date
- getdate
- gettimeofday
- gmdate
- gmmktime
- gmstrftime
- idate
- localtime
- microtime
- mktime
- strftime
- strptime
- strtotime
- time
- timezone_abbreviations_list
- timezone_identifiers_list
- timezone_location_get
- timezone_name_from_abbr
- timezone_name_get
- timezone_offset_get
- timezone_open
- timezone_transitions_get
- timezone_version_get
date_timezone_set
The procedural version takes the DateTime object as its first argument.
Parameters
Procedural style only: A DateTime object returned by date_create() . The function modifies this object.
A DateTimeZone object representing the desired time zone.
Return Values
Returns the DateTime object for method chaining. The underlaying point-in-time is not changed when calling this method.
Examples
Example #1 DateTime::setTimeZone() example
$date = new DateTime ( ‘2000-01-01’ , new DateTimeZone ( ‘Pacific/Nauru’ ));
echo $date -> format ( ‘Y-m-d H:i:sP’ ) . «\n» ;?php
$date -> setTimezone (new DateTimeZone ( ‘Pacific/Chatham’ ));
echo $date -> format ( ‘Y-m-d H:i:sP’ ) . «\n» ;
?>$date = date_create ( ‘2000-01-01’ , timezone_open ( ‘Pacific/Nauru’ ));
echo date_format ( $date , ‘Y-m-d H:i:sP’ ) . «\n» ;?php
date_timezone_set ( $date , timezone_open ( ‘Pacific/Chatham’ ));
echo date_format ( $date , ‘Y-m-d H:i:sP’ ) . «\n» ;
?>The above examples will output:
2000-01-01 00:00:00+12:00 2000-01-01 01:45:00+13:45
See Also
- DateTimeImmutable::setTimezone() — Sets the time zone
- DateTime::getTimezone() — Return time zone relative to given DateTime
- DateTimeZone::__construct() — Creates new DateTimeZone object
User Contributed Notes