Манипуляции с датой и временем

Раздел: Работа с данными -> Работа с датой и временем в PHP

Работа с датами в 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.2025

Php дата создания (работа с датой в 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 days
367
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

Работа с датой в PHP - comments

En
Php дата создания (php)