Дата и время
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 усреднённые, поэтому используйте их
только для грубых оценок.