Работа с датами в PHP
1. DateTime
vs DateTimeImmutable
✅ DateTime
- Изменяемый объект
- Методы, такие как
modify()
иadd()
, меняют исходный объект
$date = new DateTime('2020-01-01');
$date->modify('+1 day');
echo $date->format('Y-m-d'); // 2020-01-02
✅ DateTimeImmutable
- Неизменяемый объект
- Все изменения возвращают новый объект, старый остаётся прежним
$date = new DateTimeImmutable('2020-01-01');
$newDate = $date->modify('+1 day');
echo $date->format('Y-m-d'); // 2020-01-01
echo $newDate->format('Y-m-d'); // 2020-01-02
2. DateTimeInterface
Это интерфейс, реализуемый DateTime
и DateTimeImmutable
.
✅ Используйте его в типизации методов, чтобы не привязываться к конкретной реализации:
function formatDate(\DateTimeInterface $date): string {
return $date->format('Y-m-d');
}
3. Частые манипуляции с датами
➕ modify()
$date = new DateTimeImmutable('2024-05-01');
$nextMonth = $date->modify('+1 month'); // 2024-06-01
⏱ diff()
$birth = new DateTime('2000-01-01');
$now = new DateTime();
$age = $birth->diff($now)->y; // Получить возраст
📆 add()
и sub()
$date = new DateTimeImmutable('2024-01-01');
$interval = new DateInterval('P10D'); // 10 дней
$newDate = $date->add($interval); // 2024-01-11
🔁 Сравнение дат
if ($date1 > $date2) {
echo 'date1 позже date2';
}
4. 🧮 DateInterval
: Что это и зачем нужен?
DateInterval
— это объект, представляющий интервал (разницу) между датами или "отрезок времени", который можно добавить/отнять от даты.
$interval = new DateInterval('P10D'); // 10 дней
$date->add($interval); // прибавит 10 дней
$date->sub($interval); // отнимет 10 дней
Формат ISO 8601:
P
— "Period"T
— перед временем (Time)P1Y2M3DT4H5M6S
— 1 год, 2 мес., 3 дня, 4 часа, 5 минут, 6 сек
$interval = new DateInterval('P1Y2M'); // 1 год и 2 месяца
Пример: выдать документ, действующий 14 дней
$issuedAt = new DateTimeImmutable();
$validUntil = $issuedAt->add(new DateInterval('P14D'));
5. Полезные методы
Метод | Назначение |
---|---|
format('Y-m-d') | Строковое представление |
setTime(h, m, s) | Установка времени |
setDate(y, m, d) | Установка даты |
getTimestamp() | UNIX timestamp |
createFromFormat() | Создание из произвольного формата |
6. Работа с временными зонами
$tz = new DateTimeZone('Europe/Moscow');
$now = new DateTime('now', $tz);
6. Примеры из практики
✅ Проверка возраста 20 лет
function isAfterTwentyYears(DateTimeInterface $birthDate, DateTimeInterface $issuedDate): bool {
$twentyYears = (new DateTimeImmutable($birthDate->format('Y-m-d')))->modify('+20 years');
return $issuedDate >= $twentyYears;
}
✅ Получить возраст в годах
function getAge(DateTimeInterface $birthDate): int {
return $birthDate->diff(new DateTimeImmutable())->y;
}
✅ Обрезать дату до начала дня (00:00:00)
function startOfDay(DateTimeInterface $date): DateTimeImmutable {
return (new DateTimeImmutable($date->format('Y-m-d')))->setTime(0, 0);
}
7. Не хардкоди now
— прокидывай текущую дату зависимостью
Это ключевая практика для тестируемости и гибкости:
❌ Плохо:
if ($someDate < new DateTimeImmutable()) {
...
}
✅ Хорошо:
function isExpired(DateTimeInterface $checkDate, DateTimeInterface $now): bool {
return $checkDate < $now;
}
8. Рекомендации и best practices
- ✅ Используй
DateTimeImmutable
по умолчанию — это безопаснее и предсказуемо - ✅ Типизируй параметры через
DateTimeInterface
- ✅ Используй
DateInterval
для работы с интервалами - ✅ Сохраняй даты в UTC и показывай пользователю с учётом временной зоны
- ✅ Не хардкоди
now
— прокидывай текущую дату в зависимости
🎁 Бонус: Класс-помощник
class DateHelper
{
public static function addDays(DateTimeInterface $date, int $days): DateTimeImmutable
{
return (new DateTimeImmutable($date->format('Y-m-d')))->modify("+{$days} days");
}
public static function isExpired(DateTimeInterface $date): bool
{
return $date < new DateTimeImmutable();
}
public static function formatIso(DateTimeInterface $date): string
{
return $date->format(DateTime::ATOM);
}
}
Работа с датами в PHP может быть простой и безопасной, если использовать DateTimeImmutable
, правильно типизировать методы и применять стандартные инструменты. Это повышает читаемость кода, избавляет от багов и облегчает тестирование.
Итоги
- Все методы
DateTime
работают также сDateTimeImmutable
. - Главное отличие:
DateTimeImmutable
не изменяет объект, а создаёт новый, в то время какDateTime
изменяет сам объект. - Оба класса реализуют интерфейс
DateTimeInterface
, что позволяет использовать их в одном контексте и передавать в функции с типизацией через этот интерфейс.
Используя DateTimeImmutable
, вы избегаете случайных побочных эффектов, что делает код более предсказуемым и безопасным.
Похожие статьи
Что такое Ngrok и как им пользоваться при разработке Telegram-бота
Как с помощью ngrok быстро настроить локальную разработку Telegram-бота с вебхуками, получить публичный HTTPS-адрес и протестировать бота без настройки хостинга и открытия портов.
Читать дальше...