Дата и время

Nette предлагает для работы с датой и временем два класса: Nette\Utils\DateTimeImmutable (неизменяемый, рекомендуемый) и Nette\Utils\DateTime (изменяемый). Оба расширяют нативные классы PHP, поэтому все нативные методы остаются доступны, и добавляют одни и те же два улучшения.

Во-первых, они строгие. PHP молча принимает некорректные даты вроде 0000-00-00 (превращает в -0001-11-30) или 2024-02-31 (превращает в 2024-03-02), а эти классы вместо этого выбрасывают исключение.

Во-вторых, они исправляют поведение при переходах на летнее и зимнее время (DST), когда в нативном PHP добавление относительного времени (например, +100 minutes) может дать более раннее время, чем добавление меньшего промежутка (например, +50 minutes). Эти классы обеспечивают интуитивную арифметику, и +100 minutes всегда больше, чем +50 minutes.

Установка:

composer require nette/utils

Неизменяемый или изменяемый?

Класс DateTimeImmutable доступен начиная с версии 4.1.5 и является рекомендуемым выбором. Каждый изменяющий метод возвращает новый экземпляр вместо изменения исходного, поэтому объект, который вы сохранили или передали в функцию, никогда не изменится неожиданно:

use Nette\Utils\DateTimeImmutable;

$date = new DateTimeImmutable('2024-02-26');
$next = $date->modify('+1 day');
echo $date; // 2024-02-26 00:00:00  (без изменений)
echo $next; // 2024-02-27 00:00:00  (новый объект)

DateTime изменяемый: тот же вызов меняет объект на месте. Он не объявлен устаревшим, но для нового кода предпочтителен неизменяемый вариант.

use Nette\Utils\DateTime;

$date = new DateTime('2024-02-26');
$date->modify('+1 day');
echo $date; // 2024-02-27 00:00:00  (оригинал изменился)

Поскольку оба класса расширяют нативные, вы продолжаете пользоваться уже знакомыми методами: format(), getTimestamp(), add(), sub(), diff(), setTimezone(), операторами сравнения и так далее. У DateTimeImmutable все изменяющие методы возвращают новый экземпляр. Остальная часть этой страницы описывает только то, что Nette добавляет сверху; если не сказано иное, всё работает одинаково в обоих классах.

Создание объектов

static from (string|int|\DateTimeInterface|null $time)static

Создаёт объект из строки, UNIX-времени или другого объекта DateTimeInterface. null означает текущее время. Выбрасывает исключение, если дата и время некорректны.

DateTimeImmutable::from(1_138_013_640); // из UNIX-времени, в часовом поясе по умолчанию
DateTimeImmutable::from('1994-02-26 04:15:32'); // из строки
DateTimeImmutable::from('1994-02-26'); // из даты, время будет 00:00:00
DateTimeImmutable::from(null); // текущие дата и время

static fromParts (int $year, int $month, int $day, int $hour=0, int $minute=0, float $second=0.0)static

Создаёт объект из отдельных составляющих или выбрасывает исключение, если дата и время некорректны.

DateTimeImmutable::fromParts(1994, 2, 26, 4, 15, 32);

static createFromFormat (string $format, string $datetime, string|\DateTimeZone|null $timezone=null): static|false

Расширяет нативный DateTime::createFromFormat возможностью задать часовой пояс строкой.

DateTimeImmutable::createFromFormat('d.m.Y', '26.02.1994', 'Europe/London');

Строгая проверка

Некорректные дата или время никогда не подправляются молча, всегда выбрасывается исключение. Это относится к любому способу создания или изменения объекта: конструктору, from(), fromParts() и методам setDate() и setTime().

new DateTimeImmutable('2024-02-31');         // выбрасывает (31 февраля не бывает)
DateTimeImmutable::fromParts(2024, 2, 31);   // выбрасывает
$date->setDate(2024, 2, 31);                 // выбрасывает
$date->setTime(25, 0);                       // выбрасывает (25-го часа не бывает)

Вывод в строку и JSON

__toString() возвращает дату и время в формате Y-m-d H:i:s, поэтому объект можно напрямую выводить или соединять со строками:

echo $date; // '2017-02-03 04:15:32'

Оба класса реализуют JsonSerializable и сериализуются в формат ISO 8601, широко используемый в JavaScript:

echo json_encode($date); // '"2017-02-03T04:15:32+01:00"'

Дополнительные возможности DateTime

Изменяемый DateTime несёт несколько дополнительных членов, которые имеют смысл только для изменяемого объекта и потому не входят в DateTimeImmutable.

Его метод from() трактует небольшое число ещё и как смещение в секундах от текущего времени. Неизменяемый вариант намеренно обходится без этого сокращения: там число всегда означает буквальное значение времени.

DateTime::from(42); // текущее время плюс 42 секунды

modifyClone(string $modify=''): static возвращает изменённую копию и оставляет оригинал нетронутым. У изменяемого объекта он даёт то, что у неизменяемого вы получаете бесплатно через modify():

$original = DateTime::from('2017-02-03');
$clone = $original->modifyClone('+1 day');
$original->format('Y-m-d'); // '2017-02-03'  (без изменений)
$clone->format('Y-m-d');    // '2017-02-04'

DateTime::relativeToSeconds(string $relativeTime): int преобразует строку относительного времени в секунды:

DateTime::relativeToSeconds('1 minute'); // 60
DateTime::relativeToSeconds('-1 hour'); // -3600

Наконец, DateTime определяет константы MINUTE, HOUR, DAY, WEEK, MONTH и YEAR, выражающие длительность в секундах; MONTH и YEAR усреднённые, поэтому используйте их только для грубых оценок.

версия: 4.x