DateTime в PHP

Начиная с версии 5.2 в PHP появился такой тип данных как DateTime. Попробуем в этой статье разобраться почему лучше использовать его вместо старых функций date() и time().

Функция date() используется для строкового отображения даты/времени. Функция принимает два параметра, 1-ый — формат возвращаемой строки, а второй — само значение даты. По умолчанию второй параметр принимает значение текущего момента времени, либо можно указать отметку времени в unix формате (timestamp).

<?php
// Текущая дата
echo date("Y-m-d", time());
// 2013-12-01
echo date("Y-m-d", 1385925192);

Функция time() возвращает текущее время в unix формате (timestamp).

<?php
// Текущее время, unix формат
echo time();

Datetime()

Объект Datetime впервые был представлен в PHP версии 5.2, он содержит в себе множество вспомогательных объектов, для решения проблем, с которыми вам приходилось сталкиваться при использовании функций date() и time(). Также был представлен объект DateTimeZone, который управляет часовым поясом, объект DateInterval соответствует интервалу времени (например 2 дня) от настоящего момента, DatePeriod показывает разницу во времени между двумя разными датами. Основное преимущество использования DateTime перед старыми функциями заключается в том, что значения дат проще изменять. Если вы хотите получить значение времени и даты при помощи функции date(), то вы напишите следующее:

<?php
echo date("l jS \of F Y h:i:s A");

А вот пример для установки часового пояса:

<?php
date_default_timezone_set('UTC');
echo date("l jS \of F Y h:i:s A");

Проблема возникает при необходимости изменить или сравнить две отметки времени, DateTime имеет методы modify() и diff() упрощающие задачу. Преимущества DateTime проявляются когда вы манипулируете значениями дат.

Сначала объект надо инициализировать

<?php
$date = new DateTime();

Конструктор этого класса принимает два параметра. Первый — значение времени, вы можете использовать строку в формате функции date, время в формате Unix, интервал или период. Второй параметр — часовой пояс.

<?php
// Установка даты
$date = new DateTime('2000-01-01');
// Установка даты с часовым поясом
$date = new DateTime('2000-01-01', new DateTimeZone('Pacific/Nauru'));
// Установка даты на 4 дня вперед
$date = new DateTime('+4 days');

Вывод форматированной даты

Объект DateTime может работать также как и функция date, всего лишь необходимо вызвать метод format() указав формат возвращаемой строки.

<?php
echo $date->format('Y-m-d');

Вывод отметки времени (timestamp)

Для вывода отметки времени в формате Unix существует метод getTimestamp().

~~~{.php} <?php

$date = new DateTime(); echo $date->getTimestamp();


### Установка даты
Несмотря на то, что значение даты вы указываете при создании объекта класса, вы можете позже изменять это значение.
### Изменение даты
Для изменения даты используйте метод `setDate()`.
~~~php
<?php
$date = new DateTime();
// 2001-02-03
$date->setDate(2001, 2, 3);
echo $date->format('Y-m-d');

Изменение времени

Для изменения значения времени существует метод setTime().

<?php
$date = new DateTime();
// 2013-12-01 14:55:00
$date->setTime(14, 55);
echo $date->format('Y-m-d H:i:s');

Изменение метки timestamp

Для этого придуман метод setTimestamp().

<?php
$date = new DateTime();
// 2013-11-28 19:13:19
$date->setTimestamp(1385665999);
echo $date->format('Y-m-d H:i:s');

Установка часового пояса

Второй параметр при создании объекта — DateTimeZone, он позволяет назначить часовой пояс нашему объекту. Это означает, что мы сможем легко сравнивать два значения времени из разных часовых поясов и получать корректную разницу.

<?php
// 2013-12-01 13:45:00+13:45
$date = new DateTime('2013-12-01', new DateTimeZone('Pacific/Chatham'));
echo $date->format('Y-m-d H:i:sP');

Также для установки этого значения существует метод setTimezone().

<?php
$date = new DateTime('2013-12-01');
// 2013-12-01 13:45:00+13:45
$date->setTimezone(new DateTimeZone('Pacific/Chatham'));
echo $date->format('Y-m-d H:i:sP');
// 2013-11-30 19:00:00-05:00
$date->setTimezone(new DateTimeZone('America/Toronto'));
echo $date->format('Y-m-d H:i:sP');

Полный список часовых поясов можно просмотреть на php.net.

Как добавить дни к значению даты

Для изменения значения даты в объекте DateTime можно использовать метод modify(). Он принимает в качестве параметра строковое значение дней, месяцев, года. Например, если хотите прибавить несколько дней, например 3 дня, один месяц и один год:

<?php
$date = new DateTime('2013-12-01');
$date->modify('+3 day');
// 2013-12-04
echo $date->format('Y-m-d');
$date = new DateTime('2013-12-01');
$date->modify('+1 month');
// 2014-01-01
echo $date->format('Y-m-d');

Сравнение двух дат

<?php
$date1 = new DateTime('May 13th, 1986');
$date2 = new DateTime('October 28th, 1989');
$difference = $date1->diff($date2);

Код выше даст нам разницу двух дат в виде DateInterval.

DateInterval Object
(
   [y] => 3
   [m] => 5
   [d] => 15
   [h] => 0
   [i] => 0
   [s] => 0
   [invert] => 0
   [days] => 1264
)

Конвертация номера месяца и имени месяца

Довольно часто приходится получать имя месяца из его порядкового номера, для этого всего лишь нужно указать формат “F” в качестве первого параметра

<?php
$monthName = date("F", mktime(0, 0, 0, $monthNum));

При использовании класса DateTime можно применить метод format().

<?php
$date = new DateTime('2000-'.$monthNum.'-01');
$monthName = $date->format("F");

Получаем количество недель в месяце

Следующий пример поможет вам получить количество недель в определенном месяце года.

<?php
function weeks_in_month($month, $year)
{
   $startDate = new DateTime();
   $startDate->setDate($year, $month, 1);
   $loopDate = $startDate;
   $week = 1;
   for($i = $startDate->format('d'); $i <= cal_days_in_month(CAL_GREGORIAN, $month, $year); $i++)
   {
       if($loopDate->format('w') % 7 == 0)
       {
           $week++;
       }
       $loopDate->modify('+1 day');
   }
   return $week;
}
echo '<p>Jan '.weeks_in_month(1, 2014).'</p>';
echo '<p>Feb '.weeks_in_month(2, 2014).'</p>';
echo '<p>Mar '.weeks_in_month(3, 2014).'</p>';
echo '<p>Apr '.weeks_in_month(4, 2014).'</p>';
echo '<p>May '.weeks_in_month(5, 2014).'</p>';
echo '<p>Jun '.weeks_in_month(6, 2014).'</p>';
echo '<p>Jul '.weeks_in_month(7, 2014).'</p>';
echo '<p>Aug '.weeks_in_month(8, 2014).'</p>';
echo '<p>Sep '.weeks_in_month(9, 2014).'</p>';
echo '<p>Oct '.weeks_in_month(10, 2014).'</p>';
echo '<p>Nov '.weeks_in_month(11, 2014).'</p>';
echo '<p>Dec '.weeks_in_month(12, 2014).'</p>';
?>