PHP-расширение Date / Time представляет собой набор классов, которые позволяют вам работать практически со всеми задачами, связанными с датой и временем. Он был доступен с момента выпуска PHP 5.2, и расширение представило несколько новых классов, все из которых сопоставлены с реальными сценариями:
-
Дата или время представлены объектом
DateTime
. - Часовой пояс мира представлен объектом
DateTimeZone
. - Объекты
DateInterval
представляют интервал. Например, когда мы говорим «два дня», «два дня» — это интервал. ОбъектDateInterval
не зависит от конкретной даты или времени. - Объекты
DatePeriod
представляют период между двумя датами.
Теперь не позволяйте двум последним заметить вас, мы рассмотрим их использование в реальных условиях.
От date()
до date()
Всякий раз, когда мы хотим показать дату, которую мы использовали date()
, это просто и работает. Вам просто нужно передать нужный вам формат даты. Но манипулировать им очень сложно, хорошим примером является форматирование даты и времени в соответствии с пользовательским часовым поясом.
DateTime делает больше, чем просто возвращает отформатированную дату, но прежде чем мы пойдем дальше, вам нужно инициировать новый объект DateTime
который представляет вашу дату и / или время. Тогда мы можем делать с ней все классные вещи. Новый экземпляр создается так же, как и любой другой класс PHP.
1
|
$date = new DateTime();
|
Конструктор DateTime принимает строковый параметр, который по умолчанию равен «сейчас», текущему времени и дате. Чтобы создать объект на определенную дату, вы должны передать ему определенную дату и время. Форматирование параметра в большинстве случаев говорит само за себя. Ниже вы можете найти несколько различных примеров построения вашего объекта DateTime
:
1
2
3
4
|
new DateTime(‘2013, March 24’) //DateTime representing 2013, March 24
new DateTime(‘2013-03-24’) //DateTime representing 2013, March 24
new DateTime(‘+2 days’) //DateTime representing 2 days from now on.
new DateTime(‘tomorrow’)
|
Когда PHP трудно понять формат, он выдаст исключение. Полный список доступного форматирования можно найти в документации
Если форматирование не соответствует вашим потребностям, вы можете указать свой собственный формат, используя DateTime::createFromFormat
1
|
DateTime::createFromFormat(‘jM-Y’, ’24-Mar-2013′);
|
Теперь, когда у нас есть объект DateTime, мы можем довольно легко сделать целый ряд вещей.
Unix Timestamp
1
|
$date->getTimestamp();
|
Изменение даты / времени
1
2
3
4
|
$date->setDate(2013, 12, 30);
$date->setTime(12, 3, 20);
$date->modify(‘tomorrow’);
$date->setTimestamp(1364798550);
|
Обратите внимание, что когда заданы значения вне допустимого диапазона, PHP изменит дату соответствующим образом. Например, $date->setDate(2013, 12, 35);
будет генерировать 2014-01-04
, то же самое касается времени.
Работа с несколькими датами
Теперь, когда вы одержимы DateTime, следующее, что вы знаете, ваши приложения будут заполнены объектами DateTime. Вы начнете любить даты и время, как никогда раньше. Отныне вы будете иметь дело с объектами DateTime, а не со «строками», которые вы должны передавать в функцию strtotime
когда вам нужно немного подсчитать.
Скажем, например, что вам нужно сравнить два дня рождения:
1
2
3
4
5
|
$sheldon = new DateTime(‘May 20th, 1980’);
$neo = new DateTime(‘March 11th, 1962’);
if ($sheldon > $neo)
echo ‘Sheldon is younger than neo’;
|
Другой сценарий может быть сравнение двух дат. Мы можем сравнить даты друг с другом следующим образом:
1
|
$diff = $neo->diff($sheldon);
|
Вызов diff
возвращает объект DateInterval. Если мы выбрасываем возвращаемое значение:
01
02
03
04
05
06
07
08
09
10
11
|
DateInterval Object
(
[y] => 18
[m] => 2
[d] => 9
[h] => 0
[i] => 0
[s] => 0
[invert] => 0
[days] => 6645
)
|
Это публичные объекты. Вы можете сгенерировать дружественный вывод из объекта DateInterval:
1
|
$diff->format(‘Neo is older by %Y years and %m months older’);
|
Что лучше всего в объекте DateInterval, так это то, что вы можете применить интервал к другому объекту DateTime:
1
|
$neo->add($diff);
|
Примечание. Изменения в DateTime, такие как добавление, не возвращают новые объекты DateTime, а влияют на исходный объект. Всегда помните об этом при передаче объектов DateTime по всему вашему приложению. В PHP 5.5 появился новый класс, который возвращает новые объекты после модификации.
diff
— не единственное место, где вы можете создать объект DateInterval. Поскольку это класс, новые объекты могут быть инициированы как обычно:
1
|
$new_diff = new DateInterval(‘P2Y’);
|
Количество лет / месяцев / дней и т. Д. Передается конструктору в виде строки. Более подробную информацию можно найти в документации конструктора .
Работа с часовыми поясами
При создании новых объектов DateTime второй аргумент конструктора определяет часовой пояс. Если мы пропустим это, часовой пояс по умолчанию будет date.timezone
в php.ini
. Вы можете изменить это во время выполнения, вызвав date_default_timezone_set
:
1
2
|
date_default_timezone_set(‘America/New_York’);
new DateTime(‘today’);
|
Вы также можете менять часовые пояса на лету. Как вы уже догадались, сначала нам нужен объект Timezone.
1
2
|
$timezone = new DateTimeZone(‘America/New_York’);
$sheldon->setTimezone($timezone);
|
Вы можете определить часовой пояс при создании вашего нового объекта DateTime:
1
|
$sheldon = new DateTime(‘May 20th, 1980’, $timezone);
|
Однако важно отметить, что setTimezone
изменяет исходный объект DateTime. В основном мы просим «форматировать эту дату в этот часовой пояс» всякий раз, когда мы вызываем метод setTimezone
. С другой стороны, в последнем примере, где мы передаем часовой пояс в конструктор DateTime, мы говорим: «Дата, которую я создаю, находится в этом часовом поясе».
Список действительных часовых поясов доступен в онлайн-документации .
DatePeriods
Я думаю, что официальное руководство дает лучшее объяснение:
Период даты позволяет выполнять итерацию по набору дат и времени, повторяющихся через равные промежутки времени в течение заданного периода.
DatePeriod позволяет нам генерировать набор DateTimes, используя два дня, которые мы определяем между интервалами. Мы пропускаем дату начала, интервал и дату окончания. На каждом интервале создается новый объект DateTime.
Допустим, мы хотим получить все даты рождения Шелдона, начиная с его рождения:
01
02
03
04
05
06
07
08
09
10
|
//since birthdays occur every year, the interval is one year
$interval = new DateInterval(‘P1Y’);
//third argument is the end date, new DateTime() == right now
$period = new DatePeriod($sheldon, $interval, new DateTime());
foreach($period as $dt) {
//DateTime objects
echo $dt->format(‘Ymd — D’), «\n»;
}
|
Результат будет:
1
2
3
4
5
6
7
|
1981-05-20 — Wed
1982-05-20 — Thu
1983-05-20 — Fri
1984-05-20 — Sun
1985-05-20 — Mon
1986-05-20 — Tue
…
|
Теперь по умолчанию DatePeriod
включает начальную дату, которую мы передаем. Однако четвертый аргумент конструктора позволяет нам пропустить начальную дату:
1
|
$period = new DatePeriod($sheldon, $interval, new DateTime(), DatePeriod::EXCLUDE_START_DATE);
|
Давайте посмотрим, сколько вечеринок у Нео было до рождения Шелдона:
1
2
|
$bdays = new DatePeriod($neo, $interval, $sheldon, DatePeriod::EXCLUDE_START_DATE);
echo iterator_count($bdays);
|
простирающийся
Все классы, которые мы рассмотрели сегодня, могут быть расширены для использования с вашими собственными методами. Одно из популярных применений — расширение DateTime методом __toString
чтобы вы могли правильно распечатать объект DateTime без вызова format
.
Сценарии использования пары
-
Один из моих личных подходов к использованию объектов DateTime — это работа со столбцами даты / времени в базах данных. Все даты хранятся как даты часового пояса UTC. Код приложения работает только с объектами DateTime, но перед созданием конечного запроса все даты форматируются в UTC. Этот подход позволил мне легко работать с несколькими входами часового пояса.
Я могу передать нью-йоркский объект времени и полностью забыть о его форматировании, прежде чем перейти к базе данных. Я могу легко переключаться между метками времени Unix и обычным форматированием даты и времени в моей базе данных в любое время, мой код приложения не заботится, пока он получает объект DateTime.
- Я также использовал DateInterval для упрощения логики оплаты подписки. Использование объектов DateInterval для определения времени между подпиской значительно упростило задачу. Мне просто нужно применить интервал до последней даты оплаты.
У вас есть хорошие примеры использования даты / времени? Поделитесь ими в комментариях.
Заворачивать
Расширение даты и времени может многое предложить, если вы находитесь на переднем крае, с PHP 5.5 появились новые классы и интерфейсы. Обязательно ознакомьтесь с руководством. Спасибо за прочтение.