При работе на любом языке программирования работа с датами и временем часто является тривиальной и простой задачей. То есть, пока не будут поддерживаться часовые пояса. К счастью, в PHP есть один из самых мощных инструментов даты / времени, которые помогут вам справиться со всеми видами проблем, связанных с временем: отметки времени Unix, форматирование дат для потребления человеком, отображение времени с часовыми поясами, разница между текущим и вторым Вторник следующего месяца и т. Д. В этой статье я познакомлю вас с основами PHP-функций времени ( time()
mktime()
date()
PHP Дата и Время Функции
Большая часть этой статьи будет работать со временем Unix, или POSIX или временем эпохи, как это иначе известно. Время представляется в виде смещения в количестве секунд, отсчитываемых с полуночи 1 января 1970 года по Гринвичу. Если вы заинтересованы в полной истории времени Unix, посмотрите статью о времени Unix в Википедии .
UTC, также известное под своим полным названием «Всемирное координированное время», также называемое «GMT», а иногда «зулусское время», — это время на долготе 0 градусов. Все остальные часовые пояса в мире выражены как положительные или отрицательные смещения от этого времени. Обработка времени в UTC и Unix облегчит вашу жизнь, когда вам нужно иметь дело с часовыми поясами. Я расскажу об этом позже, но давайте пока проигнорируем проблемы с часовыми поясами и рассмотрим некоторые временные функции.
Получение текущего времени Unix
time()
Чтобы проиллюстрировать это, я буду использовать интерактивную оболочку CLI PHP.
Шон @ beerhaus: ~ $ php -a php> время печати (); 1324402770
Если вам нужно представление массива времени Unix, используйте getdate()
Он принимает необязательный аргумент метки времени Unix, но по умолчанию принимает значение time()
php> $ unixTime = time (); php> print_r (getdate ($ unixTime)); массив ( [секунд] => 48 [минуты] => 54 [часы] => 12 [mday] => 20 [wday] => 2 [пн] => 12 [год] => 2011 [yday] => 353 [weekday] => вторник [месяц] => декабрь [0] => 1324403688 )
Форматирование времени Unix
Время Unix может быть легко отформатировано практически в любую строку, которую человек захочет прочитать. date()
Если дополнительная временная метка не указана, используется значение time()
php> печатать дату ("r", $ unixTime); Вт, 20 дек 2011 12:54:48 -0500
Строка форматирования «r» возвращает время, отформатированное в соответствии с RFC 2822. Конечно, вы можете использовать другие спецификаторы для определения ваших собственных пользовательских форматов.
php> печатать дату ("m / d / yh: i: sa", $ unixTime); 20.12.11 12:54:48 php> распечатать дату ("м / д / ч: я: са"); 20.12.11 01:12:11 php> печатать дату ("jS of FY", $ unixTime); 20 декабря 2011
Полный список допустимых символов форматирования см. На странице date()
в документации PHP. Однако эта функция становится более полезной в сочетании с функциями mktime()
strtotime()
Создание Unix Time из данного времени
mktime()
Требуется несколько целочисленных аргументов, чтобы установить каждую часть даты в следующем порядке:
mktime (час, минута, секунда, месяц, день, год, isDST)
Вы устанавливаете isDST
php> печатать дату («r», mktime (12, 0, 0, 1, 20, 1987)); Вт, 20 января 1987 г., 12:00:00 -0500 php> печатать дату ("r", mktime (0, 0, 0, дата ("n"), дата ("j"), дата ("Y"))); Вт, 20 дек 2011 00:00:00 -0500 php> печатать дату («r», mktime (23, 59, 59, дата («n»), дата («j»), дата («Y»))); Вт, 20 дек 2011 23:59:59 -0500
Вы можете видеть, что mktime()
Например, если вы храните временные метки как целые числа (время Unix) в MySQL (предзнаменование кого-либо?), Очень легко настроить общий диапазон запросов на текущий год.
<?php
$startTime = mktime(0, 0, 0, 1, 1, date("y"));
$endTime = mktime(0, 0, 0, date("m"), date("d"), date("y"));
Разбор английской даты в Unix Time
Почти волшебная функция strtotime()
Смотрите документацию для приемлемых форматов даты .
php> print strtotime ("сейчас"); 1324407707 php> печатать дату ("r", strtotime ("сейчас")); Вт, 20 дек 2011 14:01:51 -0500 php> print strtotime ("+ 1 неделя"); 1325012569 php> печатать дату ("r", strtotime ("+ 1 неделя")); Вт, 27 дек 2011 14:03:03 -0500 php> печатать дату ("r", strtotime ("следующий месяц")); Пт, 20 января 2012 14:04:20 -0500 php> печатать дату ("r", strtotime ("следующий месяц", mktime (0, 0, 0))); Пт, 20 января 2012 00:00:00 -0500 php> печатать дату ("r", strtotime ("следующий месяц", mktime (0, 0, 1, 31))); Чт, 03 марта 2011 г. 00:00:00 -0500
Объекты PHP DateTime и DateTimeZone
PHP-объект DateTime
Метод конструктора принимает строковое представление времени, очень похожее на strtotime()
Значением по умолчанию, если аргумент не указан, является «сейчас».
php> $ dt = new DateTime ("сейчас"); php> print $ dt-> format ("r"); Вт, 20 дек 2011 16:28:32 -0500 php> $ dt = new DateTime ("31 декабря 1999 12:12:12 EST"); php> print $ dt-> format ("r"); Пт, 31 декабря 1999 12:12:12 -0500
Метод DateTime
format()
Объекты DateTime
format()
php> print $ dt-> format (DATE_ATOM); 2011-12-20T15: 57: 45-05: 00 php> print $ dt-> format (DATE_ISO8601); 2011-12-20T15: 57: 45-0500 php> print $ dt-> format (DATE_RFC822); Вт, 20 дек. 15:57:45 -0500 php> print $ dt-> format (DATE_RSS); Вт, 20 дек 2011 15:57:45 -0500
Полный список констант можно найти на странице документации DateTime
.
Поскольку мы скоро будем иметь дело с часовыми поясами, давайте предоставим PHP часовой пояс по умолчанию для использования. В вашем файле конфигурации php.ini
[Дата] ; Определяет часовой пояс по умолчанию, используемый функциями даты ; http://php.net/date.timezone ; date.timezone =
Если значение date.timezone
Вы можете проверить, какое значение использует PHP с помощью date_default_timezone_get()
php> print date_default_timezone_get (); Америка / Триатлон
Давайте установим часовой пояс сервера на время UTC ( date.timezone = UTC
Вам нужно будет перезапустить Apache или оболочку CLI, чтобы увидеть изменения.
PHP DateTime
DateTimeZone
При создании нового экземпляра DateTime
DateTimeZone
php.ini
php> $ dt = new DateTime (); php> print $ dt-> getTimeZone () -> getName (); универсальное глобальное время
Полный список допустимых имен часовых поясов можно найти на странице документации о часовых поясах .
Теперь вы можете видеть разницу во времени, когда двум объектам DateTime
Например, вот пример, который конвертирует время из UTC в Америку / Нью-Йорк (EST).
php> $ dt = new DateTime (); php> print $ dt-> format ("r"); Вт, 20 дек 2011 20:57:45 +0000 php> $ tz = new DateTimeZone ("America / New_York"); php> $ dt-> setTimezone ($ tz); php> print $ dt-> gt; format ("r"); Вт, 20 дек 2011 15:57:45 -0500
Обратите внимание на смещение -0500 за декабрь. Если вы измените значение времени на летнюю дату, например, 1 июля, вы увидите, что оно знает о летнем времени (EDT).
php> $ tz = new DateTimeZone ("America / New_York"); php> $ july = new DateTime ("01.07.2011"); php> $ july-> setTimezone ($ tz); php> print $ июль - >> формат ("r"); Четверг, 30 июня 2011 г. 20:00:00 -0400
Использование дат с MySQL и PHP
Если вы использовали MySQL на любом уровне, вы, вероятно, заметили тип DATETIME
Это выглядит и пахнет как свидание, и если бы вы сказали, что это свидание, вы были бы правы. Но как только вы SELECT
У него нет информации о часовом поясе, и он уже отформатирован для потребления человеком, прежде чем человеку когда-либо понадобится на него посмотреть
* Да, я знаю, что MySQL имеет множество функций форматирования даты, но мы уже имеем дело и с PHP, который, как вы видели, надрывается при работе с форматами даты. Зачем нам его форматировать прямо из базы данных? У нас может быть несколько разных преобразований и форматов, которые мы хотим применить к нему. Лучше форматировать дату только тогда, когда ее увидит человек.
<?php
$db = new PDO("mysql:host=localhost;dbname=testdb", "dbuser", "dbpassword");
$result = $db->query("SELECT dt_date FROM some_table");
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
print_r($row);
var_dump($row["dt_date"]);
}
$result->closeCursor();
Запустив этот простой скрипт, вы увидите, что все, что у вас есть из поля DATETIME
массив ( [dt_date] => 2012-01-16 13:03:49 ) string (19) "2012-01-16 13:03:49"
Значение DATETIME
Если все, что вы когда-либо делаете, касается только одного сервера в одном часовом поясе, DATETIME
Итак, как вы справляетесь с датами и часовыми поясами с помощью PHP и MySQL? Храните даты как метки времени Unix.
Вы уже знаете, что время Unix — это количество секунд с 1 января 1970 года в UTC, так что это дает вам постоянный часовой пояс для работы, и, надеюсь, вы заметили, что многие функции даты / времени в PHP основаны на Unix метка времени.
При работе с MySQL я обычно создаю столбцы таблицы, в которых даты будут храниться как INTEGER UNSIGNED
При вставке даты вы можете использовать либо time()
UNIX_TIMESTAMP()
mysql> SELECT UNIX_TIMESTAMP (); + ------------------ + | UNIX_TIMESTAMP () | + ------------------ + | 1326738918 | + ------------------ +
Если вы хотите, чтобы MySQL форматировал дату, вы можете. Но время будет находиться в часовом поясе сервера, и я предлагаю вам отложить любое форматирование, пока вы не достигнете уровня шаблона / представления в своем веб-приложении и не будете готовы к тому, чтобы его увидели человеческие глаза.
mysql> SELECT FROM_UNIXTIME (UNIX_TIMESTAMP ()); + --------------------------------- + | FROM_UNIXTIME (UNIX_TIMESTAMP ()) | + --------------------------------- + | 2012-01-16 13:37:16 | + --------------------------------- +
В любом приложении, охватывающем часовой пояс, у вас обычно будет таблица, в которой отслеживаются пользовательские настройки часового пояса, которые затем будут считаны в значение $_SESSION
Предполагая, что у вас есть запись сеанса, которая выглядит так:
$ _SESSION ["userTZ"] => "Америка / Чикаго"
Вы можете легко преобразовать сохраненное время Unix (в UTC) в любую дату в часовом поясе конкретного пользователя.
<?php
$result = $db->query("SELECT int_date FROM some_table");
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
$dt = new DateTime();
$tz = new DateTimeZone($_SESSION["userTZ"]);
$dt->setTimestamp($row["int_date"]);
$dt->setTimezone($tz);
print $dt->format("r");
}
Это привело бы к дате «Пн, 16 января 2012 12:03:49 -0600». -0600 сообщает, что отстает от UTC на 6 часов, смещение 0.
Если бы мы изменили настройку часового пояса на America / Los_Angeles, получилась бы следующая дата:
Пн, 16 Янв 2012 10:03:49 -0800
И Америка / Нью-Йорк даст:
Пн, 16 Янв 2012 13:03:49 -0500
Резюме
Работа с датами и часовыми поясами является повседневной частью жизни многих программистов, но вам не о чем беспокоиться, если у вас есть надежные и простые в использовании библиотеки дат PHP для работы.
Вы видели, как легко получить метку времени Unix, как отформатировать дату в любой мыслимый формат, как проанализировать английское представление даты в метке времени, как добавить период времени в метку времени, и как конвертировать между часовыми поясами. Если у статьи есть два основных момента, которые следует отнять, они будут: 1) придерживаться времени Unix и 2) придерживаться UTC в качестве базового часового пояса для всех дат при работе с PHP и MySQL.
Идея все время основываться на UTC не относится только к PHP и MySQL; это считается хорошей практикой на любом языке. И если вы когда-нибудь обнаружите, что работаете на другом языке, есть большая вероятность, что вы скажете себе: «Черт возьми, почему они не могут сделать это как PHP?»
Изображение через Якобчука Василия / Shutterstock