Дата и время
************
.[perex]
Nette предлагает для работы с датой и временем два класса: [api:Nette\Utils\DateTimeImmutable] (неизменяемый, рекомендуемый) и [api:Nette\Utils\DateTime] (изменяемый). Оба расширяют нативные классы PHP, поэтому все нативные методы остаются доступны, и добавляют одни и те же два улучшения.
Во-первых, они **строгие**. PHP молча принимает некорректные даты вроде `0000-00-00` (превращает в `-0001-11-30`) или `2024-02-31` (превращает в `2024-03-02`), а эти классы вместо этого выбрасывают исключение.
Во-вторых, они **исправляют поведение** при переходах на летнее и зимнее время (DST), когда в нативном PHP добавление относительного времени (например, `+100 minutes`) может "дать более раннее время":https://phpfashion.com/en/100-minutes-is-less-than-50-php-paradoxes-during-time-changes, чем добавление меньшего промежутка (например, `+50 minutes`). Эти классы обеспечивают интуитивную арифметику, и `+100 minutes` всегда больше, чем `+50 minutes`.
Установка:
```shell
composer require nette/utils
```
Неизменяемый или изменяемый?
============================
Класс `DateTimeImmutable` доступен начиная с версии 4.1.5 и является рекомендуемым выбором. Каждый изменяющий метод возвращает **новый экземпляр** вместо изменения исходного, поэтому объект, который вы сохранили или передали в функцию, никогда не изменится неожиданно:
```php
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` изменяемый: тот же вызов меняет объект на месте. Он не объявлен устаревшим, но для нового кода предпочтителен неизменяемый вариант.
```php
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 .[method]
-----------------------------------------------------------------------
Создаёт объект из строки, UNIX-времени или другого объекта [php:DateTimeInterface]. `null` означает текущее время. Выбрасывает исключение, если дата и время некорректны.
```php
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 .[method]
------------------------------------------------------------------------------------------------------------------
Создаёт объект из отдельных составляющих или выбрасывает исключение, если дата и время некорректны.
```php
DateTimeImmutable::fromParts(1994, 2, 26, 4, 15, 32);
```
static createFromFormat(string $format, string $datetime, string|\DateTimeZone|null $timezone=null): static|false .[method]
---------------------------------------------------------------------------------------------------------------------------
Расширяет нативный [php:DateTime::createFromFormat] возможностью задать часовой пояс строкой.
```php
DateTimeImmutable::createFromFormat('d.m.Y', '26.02.1994', 'Europe/London');
```
Строгая проверка
================
Некорректные дата или время никогда не подправляются молча, всегда выбрасывается исключение. Это относится к любому способу создания или изменения объекта: конструктору, `from()`, `fromParts()` и методам `setDate()` и `setTime()`.
```php
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`, поэтому объект можно напрямую выводить или соединять со строками:
```php
echo $date; // '2017-02-03 04:15:32'
```
Оба класса реализуют `JsonSerializable` и сериализуются в формат ISO 8601, широко используемый в JavaScript:
```php
echo json_encode($date); // '"2017-02-03T04:15:32+01:00"'
```
Дополнительные возможности DateTime
===================================
Изменяемый `DateTime` несёт несколько дополнительных членов, которые имеют смысл только для изменяемого объекта и потому **не** входят в `DateTimeImmutable`.
Его метод `from()` трактует небольшое число ещё и как смещение в секундах от текущего времени. Неизменяемый вариант намеренно обходится без этого сокращения: там число всегда означает буквальное значение времени.
```php
DateTime::from(42); // текущее время плюс 42 секунды
```
`modifyClone(string $modify=''): static` возвращает изменённую копию и оставляет оригинал нетронутым. У изменяемого объекта он даёт то, что у неизменяемого вы получаете бесплатно через `modify()`:
```php
$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` преобразует строку относительного времени в секунды: .{data-version:4.0.7}
```php
DateTime::relativeToSeconds('1 minute'); // 60
DateTime::relativeToSeconds('-1 hour'); // -3600
```
Наконец, `DateTime` определяет константы `MINUTE`, `HOUR`, `DAY`, `WEEK`, `MONTH` и `YEAR`, выражающие длительность в секундах; `MONTH` и `YEAR` усреднённые, поэтому используйте их только для грубых оценок.
Дата и время
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);
Расширяет нативный 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 усреднённые, поэтому используйте их
только для грубых оценок.