Dater — определяет часовой пояс(timezone), локализует и форматирует дату-время в PHP

от автора

Когда при разработке веб-проекта встаёт задача учёта часовых поясов пользователей, то каждый раз решение как будто приходится изобретать заново. Из множества известных мне проектов решивших эту задачу я не припомню ни одного решения, которое можно было бы назвать простым, прозрачным для всей архитектуры и универсальным.

А что если хочется просто несколько строчек кода, и чтобы весь остальной код никогда не узнал, что данные клиенту нужно отдавать в другом часовом поясе, и что в данных пришедших от клиента время может быть указано с часовым поясом отличным от серверного? Для решения этой и многих других задач, сегодня я расскажу вам про одну лаконичную и функциональную библиотеку для PHP.

И так, встречайте — Dater, и его основные возможности:

  • Биндинг форматов
  • Локализация текстов и форматов
  • Расширение списка опций форматирования
  • Автоопределение часового пояса
  • Конвертация времени с учётом часового пояса
  • Автоматическая конвертация времени в $_GET, $_POST, $_REQUEST с учётом часового пояса
  • Автоматическая конвертация часового пояса в шаблоне отправляемых данных


Обещанные строчки кода по автоматическому определению и обработке пользовательского часового пояса оставим на десерт, а пока пробежимся по основным возможностям Dater, в кратце, на примерах.

Биндинг форматов

Позволяет стандартизовать для проекта набор используемых форматов и работать с ними по имени:

$dater->format(time(), 'd/m/Y'); // 2013/03/14 $dater->addFormat('slashedDate', 'd/m/Y'); $dater->format(time(), 'slashedDate'); // 2013/03/14 $dater->slashedDate(time()); // 2013/03/14 

Расширение опций форматирования

Доступны все опции форматирования из date(), которые также могут быть переопределены и расширены:

$dater->addFormatOption('ago', function (DateTime $dateTime) {     return floor((time() - $dateTime->getTimestamp()) / 86400) . ' days ago'; }); $dater->format(time() - 60*60*24*7, 'd F Y, ago'); // 14 March 2013, 7 days ago 

Поддержка локалей

$dater->setLocale(new Dater_Locale_English()); echo $dater->date(); // 03/21/2013 echo $dater->now('j F Y'); // 21 March 2013  $dater->setLocale(new Dater_Locale_Russian()); echo $dater->date(); // 21.03.2013 echo $dater->now('j F Y'); // 21 марта 2013 

Стандартные методы для серверных и пользовательских форматов с учётом локали

echo $dater->date(); // 03/21/2013 (depends on locale) echo $dater->time(); // 5:41 AM (depends on locale) echo $dater->datetime(); // 03/21/2013 5:41 (depends on locale) echo $dater->serverDate(); // 2013-03-21 echo $dater->serverTime(); // 09:41:28 echo $dater->serverDateTime(); // 2013-03-21 09:41:28 echo $dater->clientDate(); // 2013-03-21 echo $dater->clientTime(); // 05:41:28 echo $dater->clientDateTime(); // 2013-03-21 05:41:28 

Конвертация даты-времени с учётом часового пояса

$dater->setServerTimezone('Europe/Moscow'); $dater->setClientTimezone('Europe/London'); echo $dater->serverDateTime(); // 2013-03-21 08:18:06 echo $dater->clientDateTime(); // 2013-03-21 04:18:06 echo $dater->time(); // 04:18 

Стоит упомянуть, что при вызове $dater->setServerTimezone('Europe/Moscow'); функция date() и класс DateTime будут возвращать время в новом установленном часовом поясе. Чтобы это отключить передайте методу false вторым параметром.

И наконец обещанное

Код, который позволит вам автоматически определить часовой пояс клиента и выводить для него актуальную дату-время:

В заголовке глобального скрипта инициализации

$dater = new Dater(new Dater_Locale_Russian(), 'Europe/Moscow'); $timezoneDetector = new Dater_TimezoneDetector(); $dater->setClientTimezone($timezoneDetector->getClientTimezone())  $dataHandler = new Dater_DataHandler($dater); $dataHandler->enableOutputTimezoneHandler(); $dataHandler->convertRequestDataToServerTimezone(); 

В основном шаблоне

<html> 	<head> 		<?= $timezoneDetector->getHtmlJsCode() ?> 	</head> </html> 

Теперь все строки YYYY-MM-DD HH:MM:SS в отправляемых данных будут заменены на YYYY-MM-DD HH:MM:SS в автоматически определённом часовом поясе клиента. Если же вам нужно выводить дату-время в определённом формате, то достаточно добавить YYYY-MM-DD HH:MM:SS[Н m d] или YYYY-MM-DD HH:MM:SS[date] где date — забинденный в Dater формат. Также можно выводить и форматировать timestamp формат: 1363853607[d.m.Y].

Например, следующие данные:

<html> <body> 	Timestamp format: 1363238564 (не изменится) 	Timestamp format: 1363238564[Y/m/d] 	Timestamp format: 1363238564[datetime] 	Server datetime format: 2013-03-14 09:22:44[Y/m/d] 	Server datetime format: 2013-03-14 09:22:44[time] 	Server datetime format: 2013-03-14 09:22:44 </body> </html> 

Будут автоматически конвертированы в:

<html> <body> 	Timestamp format: 1363238564 (не изменится) 	Timestamp format: 2013/03/14 	Timestamp format: 14.03.2013 07:22 	Server datetime format: 2013/03/14 	Server datetime format: 07:22 	Server datetime format: 2013-03-14 07:22:44 </body> </html> 

В то же время $dataHandler->convertRequestDataToServerTimezone(); сделает так, что все YYYY-MM-DD HH:MM:SS данные поступающие от клиента будут конвертированы в YYYY-MM-DD HH:MM:SS часового пояса сервера. Таким образом сервер никогда не узнает о том, что клиента работает получает и отправляет дату-время в другом часовом поясе.

В прочем, стоит признать, что это немножко экстримальный вариант обработки часовых поясов. Более универсальным и традиционным решением было бы отказаться от использования $dataHandler->enableOutputTimezoneHandler(); и просто обрамлять вставку каждой даты-времени вызовом соответствующего метода форматирования. Например <?= $dater->date($dateTimeOrTimestamp) ?>.

О проекте

Честно признаюсь, что являюсь автором этой библиотеки, и буду очень благодарен за любую критику и помощь в доработке. Исходники выложены на GitHub под свободной BSD лицензией, пользуйтесь и распространяйте как пожелаете.

Надеюсь кому-нибудь таки пригодится 🙂

ссылка на оригинал статьи http://habrahabr.ru/post/173693/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *