🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano
CalendarDate — календарная работа уровня Carbon
Назначение
Календарная дата поверх DateTimeImmutable: арифметика месяцев/лет с контролем переполнения (addMonthsNoOverflow), границы периодов, isoFormat и diffForHumans на 6 языках — без ICU/ext-intl. Склонения строит cloud-castle/inflector.
Для чего и как применять
Замена Carbon там, где нужна лишь корректная календарная арифметика и локализованный вывод: CalendarDate::parse()/now(), затем addMonthsNoOverflow(), startOfQuarter(), diffForHumans(null, 'ru').
Пример
$date = CalendarDate::parse('2026-01-31', 'UTC');
$date->addMonthsNoOverflow(1)->format('Y-m-d'); // 2026-02-28, не «3 марта»
$date->isWeekend(); // выходной ли день
$date->diffInDays($other); // целочисленная разница
$date->next(5)->format('Y-m-d'); // ближайшая пятница
$date->subDays(5)->diffForHumans($date, 'ru'); // «5 дней назад»
Анти-паттерны
Не берите только ради тесной интеграции с Laravel (фасады, Eloquent-касты дат) — это единственное, чем Carbon здесь богаче; сам календарный API Carbon-паритетен.
Жизненный цикл
flowchart LR
A[parse / now / fromClock] --> B[CalendarDate]
B -->|addMonthsNoOverflow / startOfQuarter| B
B -->|isWeekend / diffInDays / next| B
B -->|isoFormat / diffForHumans| C[Инфлектор CloudCastle]
C --> D[Локализованная строка]
Сравнение возможности с аналогами
| Аспект | 🏆 CloudCastle | symfony | carbon | lcobucci | beste | ergebnis |
|---|---|---|---|---|---|---|
| Арифметика месяцев без переполнения | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ |
| Границы периодов (startOf/endOf) | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ |
| Предикаты дня недели и относительные (isWeekend/isToday) | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ |
| Целочисленные разницы (diffInDays…diffInYears) | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ |
| Навигация (next/previous/firstOfMonth) | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ |
| diffForHumans на 6 языках | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ |
| Локализация без ICU/ext-intl | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Дата от инъектируемых часов (детерминизм) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Всего | 🏆 8 | 0 | 6 | 0 | 0 | 0 |
🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano