Data i czas
Nette oferuje dwie klasy do pracy z datą i czasem: Nette\Utils\DateTimeImmutable (niezmienną, zalecaną) i Nette\Utils\DateTime (zmienną). Obie rozszerzają natywne klasy PHP, więc każda natywna metoda pozostaje dostępna, i dodają te same dwa usprawnienia.
Po pierwsze, są rygorystyczne. Podczas gdy PHP po cichu akceptuje nieprawidłowe daty, takie jak
0000-00-00 (zamienia na -0001-11-30) czy 2024-02-31 (zamienia na 2024-03-02),
te klasy zamiast tego zgłaszają wyjątek.
Po drugie, naprawiają zachowanie przy zmianach czasu letniego (DST), gdzie w natywnym PHP dodanie czasu względnego
(np. +100 minutes) może dać wcześniejszy czas niż
dodanie krótszego okresu (np. +50 minutes). Te klasy zapewniają, że arytmetyka działa intuicyjnie i
+100 minutes jest zawsze więcej niż +50 minutes.
Instalacja:
composer require nette/utils
Niezmienna czy zmienna?
Klasa DateTimeImmutable jest dostępna od wersji 4.1.5 i jest zalecanym wyborem. Każda metoda modyfikująca
zwraca nową instancję, zamiast zmieniać oryginał, więc obiekt, który gdzieś przechowujesz albo przekazałeś do
funkcji, nigdy nie zmieni się nieoczekiwanie:
use Nette\Utils\DateTimeImmutable;
$date = new DateTimeImmutable('2024-02-26');
$next = $date->modify('+1 day');
echo $date; // 2024-02-26 00:00:00 (bez zmian)
echo $next; // 2024-02-27 00:00:00 (nowy obiekt)
DateTime jest zmienna: to samo wywołanie zmienia obiekt w miejscu. Nie jest przestarzała, ale w nowym kodzie
preferowany jest wariant niezmienny.
use Nette\Utils\DateTime;
$date = new DateTime('2024-02-26');
$date->modify('+1 day');
echo $date; // 2024-02-27 00:00:00 (oryginał się zmienił)
Ponieważ obie klasy rozszerzają natywne, nadal używasz metod, które już znasz: format(),
getTimestamp(), add(), sub(), diff(), setTimezone(), operatorów
porównania itd. Na DateTimeImmutable wszystkie metody modyfikujące zwracają nową instancję. Reszta tej strony
opisuje tylko to, co Nette dodaje ponad to; o ile nie zaznaczono inaczej, wszystko działa tak samo w obu klasach.
Tworzenie obiektów
static from (string|int|\DateTimeInterface|null $time): static
Tworzy obiekt ze stringa, uniksowego timestampu albo innego obiektu DateTimeInterface. null oznacza bieżący czas. Zgłasza wyjątek,
jeśli data i czas nie są prawidłowe.
DateTimeImmutable::from(1_138_013_640); // z uniksowego timestampu, w domyślnej strefie czasowej
DateTimeImmutable::from('1994-02-26 04:15:32'); // ze stringa
DateTimeImmutable::from('1994-02-26'); // z daty, czas będzie 00:00:00
DateTimeImmutable::from(null); // bieżąca data i czas
static fromParts (int $year, int $month, int $day, int $hour=0, int $minute=0, float $second=0.0): static
Tworzy obiekt z poszczególnych części albo zgłasza wyjątek, jeśli data i czas nie są prawidłowe.
DateTimeImmutable::fromParts(1994, 2, 26, 4, 15, 32);
static createFromFormat (string $format, string $datetime, string|\DateTimeZone|null $timezone=null): static|false
Rozszerza natywną DateTime::createFromFormat o możliwość podania strefy czasowej jako stringa.
DateTimeImmutable::createFromFormat('d.m.Y', '26.02.1994', 'Europe/London');
Rygorystyczna walidacja
Nieprawidłowa data albo czas nigdy nie są po cichu korygowane; zawsze zgłaszany jest wyjątek. Dotyczy to każdego sposobu
utworzenia albo zmiany obiektu: konstruktora, from(), fromParts() oraz metod setDate() i
setTime().
new DateTimeImmutable('2024-02-31'); // zgłasza (luty nie ma 31.)
DateTimeImmutable::fromParts(2024, 2, 31); // zgłasza
$date->setDate(2024, 2, 31); // zgłasza
$date->setTime(25, 0); // zgłasza (nie ma 25. godziny)
Wynik tekstowy i JSON
__toString() zwraca datę i czas w formacie Y-m-d H:i:s, więc obiekt można wypisać albo od razu
konkatenować:
echo $date; // '2017-02-03 04:15:32'
Obie klasy implementują JsonSerializable i serializują się do formatu ISO 8601, powszechnie używanego w
JavaScripcie:
echo json_encode($date); // '"2017-02-03T04:15:32+01:00"'
Dodatkowe możliwości DateTime
Zmienna klasa DateTime ma kilka dodatkowych elementów, które mają sens tylko dla obiektu zmiennego i dlatego
nie wchodzą w skład DateTimeImmutable.
Jej metoda from() traktuje też małą liczbę jako przesunięcie w sekundach względem bieżącego czasu. Wariant
niezmienny celowo pomija ten skrót – tam liczba jest zawsze dosłownym timestampem.
DateTime::from(42); // bieżący czas plus 42 sekundy
modifyClone(string $modify=''): static zwraca zmodyfikowaną kopię i pozostawia oryginał nietknięty. Na
obiekcie zmiennym daje to, co na niezmiennym zapewnia za darmo modify():
$original = DateTime::from('2017-02-03');
$clone = $original->modifyClone('+1 day');
$original->format('Y-m-d'); // '2017-02-03' (bez zmian)
$clone->format('Y-m-d'); // '2017-02-04'
DateTime::relativeToSeconds(string $relativeTime): int konwertuje string z czasem względnym
na sekundy:
DateTime::relativeToSeconds('1 minute'); // 60
DateTime::relativeToSeconds('-1 hour'); // -3600
Wreszcie DateTime definiuje stałe MINUTE, HOUR, DAY, WEEK,
MONTH i YEAR wyrażające długość w sekundach; MONTH i YEAR są
wartościami średnimi, więc używaj ich tylko do zgrubnych oszacowań.