Манипуляции с датой и временем
Работа с датами в PHP начинается с понимания основных инструментов. Наиболее эффективным и гибким решением является использование встроенного класса DateTime (или его иммутабельной версии DateTimeImmutable).
Основной подход: класс DateTime
Класс DateTime позволяет создавать объекты даты и времени, выполнять форматирование, модификацию, сравнение и операции с интервалами. Пример простого создания и форматирования:
<?php
$date = new DateTime('2025-03-15 14:30:00');
echo $date->format('Y-m-d H:i:s'); // 2025-03-15 14:30:00
?>Php new datetime (создание объекта datetime в php)
Для работы с текущим моментом можно вызвать конструктор без аргументов: new DateTime('now') или new DateTime(). Установка часового пояса осуществляется через третий аргумент или метод setTimezone().
Типичные ошибки:
- Передача некорректной строки даты (например, '32-13-2020') приводит к исключению. Используйте
DateTime::createFromFormat()для строгого разбора. - Забыли указать часовой пояс - объект создаётся в часовом поясе сервера, что может не совпадать с ожидаемым.
- Путаница между изменяемым DateTime и иммутабельным DateTimeImmutable. DateTime изменяет сам объект при модификации, DateTimeImmutable возвращает новый объект.
Как получить текущую дату и время в заданном формате без создания объекта?
Функции date() и time() - классический, но ограниченный способ. date('Y-m-d H:i:s', time()) возвращает строку. Однако эти функции не поддерживают объекты, сложные манипуляции и часовые пояса без дополнительной настройки.
echo date('d.m.Y'); // 15.03.2025Php дата создания (работа с датой в php)
Проблема: date() использует часовой пояс, заданный в php.ini (date.timezone). Если он не установлен, может выводиться UTC. Рекомендуется выставлять часовой пояс через date_default_timezone_set('Europe/Moscow').
Как преобразовать текстовое представление даты в метку времени?
Функция strtotime() парсит текстовые даты (например, 'next Monday', '+2 weeks') и возвращает Unix timestamp.
$timestamp = strtotime('2025-12-31 23:59:59');
echo date('Y-m-d', $timestamp);Php datetime format (форматирование даты и времени в php)
Ошибка: если строка не распознаётся, возвращается false. Всегда проверяйте результат:
$ts = strtotime('invalid date');
if ($ts === false) { echo 'Неверный формат'; }Как создать объект даты из строки с произвольным форматом?
DateTime::createFromFormat() позволяет задать точный формат ввода, что исключает неоднозначность.
$date = DateTime::createFromFormat('d/m/Y H:i', '15/03/2025 14:30');
echo $date->format('Y-m-d'); // 2025-03-15Распространённая ошибка: несоответствие маски формата и фактической строки (например, ожидается 'm/d/Y', а дата в формате 'd/m/Y'). Внимательно сверяйте порядок.
Как выполнять операции сложения/вычитания и перебор дат?
Используйте DateInterval вместе с DateTime. add() и sub() модифицируют объект. Для перебора подходит DatePeriod.
$date = new DateTime('2025-01-01');
$interval = new DateInterval('P1M'); // один месяц
$date->add($interval);
echo $date->format('Y-m-d'); // 2025-02-01
$period = new DatePeriod(
new DateTime('2025-01-01'),
new DateInterval('P1D'),
new DateTime('2025-01-10')
);
foreach ($period as $dt) {
echo $dt->format('Y-m-d') . ' ';
}Проблемы: DateInterval для месяцев и лет может давать неожиданные результаты из-за разной длины месяцев (например, 31 января + 1 месяц = 3 марта, а не 28 февраля). Проверяйте логику и используйте modify() с осторожностью.
Как установить и сменить часовой пояс?
Третий аргумент конструктора DateTime, метод setTimezone() или глобальная настройка date_default_timezone_set().
$date = new DateTime('now', new DateTimeZone('Europe/Moscow'));
echo $date->format('Y-m-d H:i:s');
$date->setTimezone(new DateTimeZone('America/New_York'));
echo $date->format('Y-m-d H:i:s');Типичная ошибка: забвение указать часовой пояс при создании объекта приводит к использованию серверного времени, что может отличаться от требуемого. При смене пояса объект не меняет момент времени, только представление.
Продвинутые примеры работы с датами
Ниже приведены расширенные сценарии, часто встречающиеся на практике.
Вычисление возраста по дате рождения
function calculateAge($birthDate) {
$birth = new DateTime($birthDate);
$today = new DateTime('now');
$diff = $birth->diff($today);
return $diff->y;
}
echo calculateAge('1990-05-21'); // 34 (в 2025 году)Результат для даты 1990-05-21: 34
Метод diff() возвращает объект DateInterval, из которого можно извлечь годы, месяцы, дни.
Количество дней между двумя датами
$start = new DateTime('2025-01-01');
$end = new DateTime('2025-12-31');
$interval = $start->diff($end);
echo $interval->days; // 364 (не високосный год)
// или напрямую: echo (int)$start->diff($end)->format('%a');364
Итерация по всем дням месяца с пропуском выходных
$year = 2025;
$month = 2; // февраль
$firstDay = new DateTime("$year-$month-01");
$lastDay = new DateTime("$year-$month-{$firstDay->format('t')}");
$interval = new DateInterval('P1D');
$period = new DatePeriod($firstDay, $interval, $lastDay->modify('+1 day'));
$workdays = [];
foreach ($period as $day) {
$weekDay = (int)$day->format('N'); // 1-7
if ($weekDay < 6) {
$workdays[] = $day->format('Y-m-d');
}
}
print_r($workdays);Array ( [0] => 2025-02-03 [1] => 2025-02-04 ... ) (без суббот и воскресений)
Парсинг дат из логов с нестандартным форматом
$logLine = '2025/03/15_14:30:00 ERROR: something';
preg_match('/(\d{4}\/\d{2}\/\d{2}_\d{2}:\d{2}:\d{2})/', $logLine, $matches);
$date = DateTime::createFromFormat('Y/m/d_H:i:s', $matches[1]);
echo $date->format('c'); // 2025-03-15T14:30:00+00:00 (в зависимости от timezone)2025-03-15T14:30:00+00:00
Регулярное выражение извлекает часть строки, а createFromFormat точно разбирает.
Учёт високосных годов при вычислении разницы
$start = new DateTime('2024-02-28');
$end = new DateTime('2025-03-01');
$diff = $start->diff($end);
echo $diff->days; // 367 (2024 - високосный, содержит 366 дней)
echo $diff->y . ' years, ' . $diff->m . ' months, ' . $diff->d . ' days'; // 1 years, 0 months, 1 days367 1 years, 0 months, 1 days
Использование иммутабельного DateTimeImmutable для избежания побочных эффектов
$date = new DateTimeImmutable('2025-01-31');
$modified = $date->modify('+1 month');
echo $date->format('Y-m-d'); // 2025-01-31 (оригинал не изменился)
echo $modified->format('Y-m-d'); // 2025-03-03 (из-за разной длины месяцев)2025-01-31 2025-03-03
Immutable версия возвращает новый объект при каждой модификации, что безопаснее при передаче дат в функции.
Получение списка часовых поясов с разницей от UTC
$timezones = DateTimeZone::listIdentifiers(DateTimeZone::ALL);
foreach (array_slice($timezones, 0, 5) as $tz) {
$dt = new DateTime('now', new DateTimeZone($tz));
$offset = $dt->getOffset();
$hours = $offset / 3600;
echo "$tz: UTC" . ($hours >= 0 ? '+' : '') . $hours . PHP_EOL;
}Africa/Abidjan: UTC+0 Africa/Accra: UTC+0 Africa/Addis_Ababa: UTC+3 Africa/Algiers: UTC+1 Africa/Asmara: UTC+3