docs: English JsonRpcBundle docs, REST and MCP Bundle sections, package cards
uk/articles/from-tg/series/php-can-do/datetime-immutable.md
новий файл +97
−0
1
+
# DateTimeImmutable
2
+
3
+
*Коли час змінюється, а обʼєкти ні*
4
+
5
+
- **Додано у версії:** PHP 5.5
6
+
- **Що дає:** клас, який поводиться як `DateTime`, але не змінюється при модифікації, а повертає клонований обʼєкт.
7
+
8
+
## В чому суть
9
+
10
+
У PHP якщо ми зробимо зміни часу у обʼєкта `DateTime`, він змінився всюди, де передавався, бо обʼєкти в PHP завжди передаються по посиланню, і така поведінка може призвести до неочікуваної поведінки.
11
+
12
+
`DateTimeImmutable` вирішує цю проблему — будь-яка дія над датою повертає новий екземпляр, а не мутує старий.
13
+
14
+
## Коли це справді має сенс
15
+
16
+
- у DTO / Value Object — щоб час гарантовано не змінювався після передачі;
17
+
- у планувальниках, розкладах, звітах — коли ти рахуєш багато дат від базової;
18
+
- у бізнес-логіці — коли з однієї дати обчислюється інша (початок/кінець періоду, дедлайн, акція, тощо).
19
+
20
+
## Проблема, яку можна не помітити
21
+
22
+
У продакшн-коді `DateTime` часто передають між сервісами, DTO або кешують у контейнерах.
23
+
24
+
І тут трапляється типова історія:
25
+
26
+
```php
27
+
class Campaign {
28
+
public function __construct(
29
+
public string $name,
30
+
public DateTime $startsAt,
31
+
public DateTime $endsAt,
32
+
) {}
33
+
}
34
+
35
+
$base = new DateTime('2025-10-01');
36
+
$campaign = new Campaign(
37
+
name: 'Autumn Sale',
38
+
startsAt: $base,
39
+
endsAt: $base->modify('+7 days')
40
+
);
41
+
42
+
echo $campaign->startsAt->format('Y-m-d'); // 2025-10-08 ❌
43
+
echo $campaign->endsAt->format('Y-m-d'); // 2025-10-08
44
+
```
45
+
46
+
Ми очікували, що початок буде 1 жовтня, але `$base` мутував під час `modify`, як наслідок — початок і кінець однакові.
47
+
48
+
Той самий код, але з `DateTimeImmutable` працює коректно:
49
+
50
+
```php
51
+
$base = new DateTimeImmutable('2025-10-01');
52
+
$campaign = new Campaign(
53
+
name: 'Autumn Sale',
54
+
startsAt: $base,
55
+
endsAt: $base->modify('+7 days')
56
+
);
57
+
58
+
echo $campaign->startsAt->format('Y-m-d'); // 2025-10-01 ✅
59
+
echo $campaign->endsAt->format('Y-m-d'); // 2025-10-08
60
+
```
61
+
62
+
## Додатковий приклад
63
+
64
+
```php
65
+
class Period {
66
+
public function __construct(
67
+
public DateTimeImmutable $from,
68
+
public DateTimeImmutable $to
69
+
) {}
70
+
71
+
public function days(): int {
72
+
return $this->to->diff($this->from)->days;
73
+
}
74
+
}
75
+
76
+
$period = new Period(
77
+
from: $from = new DateTimeImmutable('2025-06-01'),
78
+
to: $from->modify('+10 days'),
79
+
);
80
+
81
+
echo $period->days(); // 10
82
+
```
83
+
84
+
Жодних несподіваних мутацій — об’єкт можна безпечно кешувати чи передавати далі.
85
+
86
+
## Висновок
87
+
88
+
> DateTimeImmutable — це безпечний вибір для роботи з логікою часу.
89
+
> Він виключає випадкові зміни дат, коли одна змінна призводить до неочікуваних результатів.
90
+
91
+
Якщо твоя дата здатна змінитись — вона рано чи пізно зламає щось у звіті, логіці або фінансах. `Immutable` цього не дозволить.
92
+
93
+
← [Попередня: Генератори](/articles/from-tg/series/php-can-do/generators) · [Уся серія](/articles/from-tg/series/php-can-do) · [Наступна: Іменовані аргументи →](/articles/from-tg/series/php-can-do/named-arguments)
94
+
95
+
---
96
+
97
+
*Вперше опубліковано в Telegram-каналі [«Створений щоб помирати»](https://t.me/php_while_true/81) 21.10.2025.*