Создание объекта DateTime: от основ до продвинутых приёмов

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

Создание объекта DateTime в PHP

Как создать объект DateTime с текущей датой и временем?

Наиболее простой и распространённый способ – использование конструктора без аргументов или с аргументом 'now'. Такой объект будет содержать текущий момент времени с учётом часового пояса, установленного в конфигурации PHP (по умолчанию UTC).


$date = new DateTime();
echo $date->format('Y-m-d H:i:s'); // вывод текущей даты и времени
  

Php new datetime (создание объекта datetime в php)

2025-03-16 14:25:30
  

Php дата создания (работа с датой в php)

Если требуется явно указать часовой пояс, второй параметр конструктора принимает объект DateTimeZone.


$date = new DateTime('now', new DateTimeZone('Europe/Moscow'));
echo $date->format('Y-m-d H:i:s T');
  

Php datetime format (форматирование даты и времени в php)

2025-03-16 17:25:30 MSK
  

Типичная ошибка:

Если строка, переданная в конструктор, не распознаётся как корректная дата/время, PHP выбрасывает исключение DateMalformedStringException (в PHP 8.0+) или Exception в более старых версиях. Необработанное исключение приводит к фатальной ошибке.


// Ошибочный код
try {
    $date = new DateTime('неправильная строка');
} catch (Exception $e) {
    echo 'Ошибка: ' . $e->getMessage();
}
    
Ошибка: DateTime::__construct(): Failed to parse time string (неправильная строка) at position 0 (н): The timezone could not be found in the database
    

Как создать объект DateTime из строки с определённой датой?

Передача строки в формате, который понимает PHP (например, YYYY-MM-DD или DD.MM.YYYY), позволяет сразу получить объект с заданной датой. Время при этом устанавливается в полночь (00:00:00).


$date = new DateTime('2025-12-31');
echo $date->format('d.m.Y H:i:s');
  
31.12.2025 00:00:00
  

Возможная проблема:

При использовании неоднозначных форматов (например, '01/02/2025') PHP может интерпретировать их как месяц/день/год в зависимости от текущей локали. Для строгого разбора рекомендуется использовать DateTime::createFromFormat().

Как указать дату и время вместе?

Можно передать полную строку с датой и временем, разделённые пробелом или буквой T.


$date = new DateTime('2025-03-16 15:30:00');
echo $date->format('r');
  
Sun, 16 Mar 2025 15:30:00 +0000
  

Как использовать относительные форматы (например, 'last day of next month')?

PHP поддерживает удобные текстовые описания дат, такие как "+2 weeks", "next Monday", "first day of January 2026". Они позволяют динамически вычислять даты без арифметики.


$date = new DateTime('last day of next month');
echo $date->format('Y-m-d');
  
2025-04-30
  

Ошибка перехода на летнее время:

При использовании относительных форматов для дат, попадающих на момент перехода часового пояса на летнее/зимнее время, возможны неожиданные сдвиги. Рекомендуется явно задавать часовой пояс или использовать DateTimeImmutable.

Как создать объект из Unix timestamp?

Метка времени в формате Unix (целое число секунд с 1 января 1970 года) передаётся в конструктор как строка с префиксом @.


$date = new DateTime('@1234567890');
echo $date->format('Y-m-d H:i:s');
  
2009-02-13 23:31:30
  

При таком способе часовой пояс всегда устанавливается в UTC. Для преобразования в другой часовой пояс после создания используется метод setTimezone().

Как создать объект из нестандартного строкового формата?

Если дата представлена в виде, отличном от того, что понимает конструктор, применяется статический метод DateTime::createFromFormat(). Он принимает формат, строку и опционально часовой пояс.


$date = DateTime::createFromFormat('d/m/Y H:i', '16/03/2025 13:45');
echo $date->format('Y-m-d H:i:s');
  
2025-03-16 13:45:00
  

Типичная ошибка:

При несовпадении формата или некорректных данных метод возвращает false, а не выбрасывает исключение. Необходима проверка возвращаемого значения.


$date = DateTime::createFromFormat('Y-m-d', '2025-03-16 15:00');
if ($date === false) {
    echo 'Не удалось разобрать строку';
} else {
    echo $date->format('Y-m-d');
}
    
Не удалось разобрать строку
    

Как указать часовой пояс при создании?

Часовой пояс можно задать вторым аргументом конструктора для всех строковых форматов (кроме Unix timestamp). Также можно передать объект DateTimeZone в метод createFromFormat третьим параметром.


$timezone = new DateTimeZone('Asia/Vladivostok');
$date = new DateTime('2025-03-16 20:00', $timezone);
echo $date->format('Y-m-d H:i:s T');
  
2025-03-16 20:00:00 VLAT
  

Как изменить уже созданный объект DateTime?

После создания объекта можно модифицировать его с помощью методов modify(), setDate(), setTime(), setTimestamp(). Важно помнить, что оригинальный объект изменяется, а не создаётся новый.


$date = new DateTime('2025-01-01');
$date->modify('+1 month');
echo $date->format('Y-m-d');
  
2025-02-01
  

Если требуется неизменяемый объект, следует использовать класс DateTimeImmutable. Его методы возвращают новый объект, не затрагивая исходный.

Итог: Для большинства задач достаточно конструктора new DateTime() с простой строкой. Для строгого разбора и нестандартных форматов применяется createFromFormat. Относительные форматы удобны для интервалов, а часовые пояса управляются через DateTimeZone. Обработка исключений обязательна при работе с пользовательским вводом.

Расширенные примеры работы с DateTime

Сравнение DateTime и DateTimeImmutable

DateTime изменяет сам объект, а DateTimeImmutable при каждом изменении возвращает новый экземпляр. Пример:

Пример

$mutable = new DateTime('2025-01-01');
$immutable = new DateTimeImmutable('2025-01-01');

$mutable->modify('+1 day');
$newImmutable = $immutable->modify('+1 day');

echo 'Mutable: ' . $mutable->format('Y-m-d') . PHP_EOL;
echo 'Immutable original: ' . $immutable->format('Y-m-d') . PHP_EOL;
echo 'Immutable new: ' . $newImmutable->format('Y-m-d');
Mutable: 2025-01-02
Immutable original: 2025-01-01
Immutable new: 2025-01-02

Добавление и вычитание интервалов (DateInterval)

Методы add() и sub() принимают объект DateInterval, который можно создать из строки вида 'P1Y2M3DT4H5M6S' или через DateInterval::createFromDateString().

Пример

$date = new DateTime('2025-03-16');
$interval = new DateInterval('P1M10D'); // 1 месяц и 10 дней
$date->add($interval);
echo $date->format('Y-m-d');
2025-04-26

Ошибка: при добавлении месяцев к дате, которой не существует (например, 31 января + 1 месяц), PHP автоматически переводит на последний день февраля (28 или 29). Это может быть неожиданно.

Пример

$date = new DateTime('2025-01-31');
$date->modify('+1 month');
echo $date->format('Y-m-d');
2025-03-03  // т.к. 28 февраля -> 1 марта? На самом деле: 31.01 -> +1 месяц = 28.02, нет 31-го, поэтому 03.03? Уточним: PHP идёт на 31 число, но февраля 31 нет, поэтому добавляет количество дней до 31. Итог: 03.03

Для защиты от такого поведения используйте DateTime::modify('last day of next month').

Форматирование с учётом локали

Класс IntlDateFormatter из расширения intl позволяет выводить даты на разных языках.

Пример

$date = new DateTime('2025-03-16');
$formatter = new IntlDateFormatter('ru_RU', IntlDateFormatter::LONG, IntlDateFormatter::NONE);
echo $formatter->format($date);
16 марта 2025 г.

Преобразование часовых поясов

Метод setTimezone() меняет часовой пояс, сохраняя тот же момент времени.

Пример

$date = new DateTime('2025-03-16 12:00:00', new DateTimeZone('UTC'));
echo 'UTC: ' . $date->format('Y-m-d H:i:s T') . PHP_EOL;
$date->setTimezone(new DateTimeZone('America/New_York'));
echo 'NY: ' . $date->format('Y-m-d H:i:s T');
UTC: 2025-03-16 12:00:00 UTC
NY: 2025-03-16 08:00:00 EDT

Использование createFromFormat с массивом возможных форматов

Если входящие строки могут соответствовать разным форматам, можно перебрать их в цикле.

Пример

$formats = ['Y-m-d', 'd/m/Y', 'd.m.Y'];
$input = '16.03.2025';
$date = null;
foreach ($formats as $fmt) {
    $date = DateTime::createFromFormat($fmt, $input);
    if ($date !== false) {
        break;
    }
}
if ($date) {
    echo $date->format('Y-m-d');
} else {
    echo 'Не удалось распознать';
}
2025-03-16

Получение количества дней между двумя датами

Пример

$start = new DateTime('2025-01-01');
$end = new DateTime('2025-03-16');
$diff = $start->diff($end);
echo 'Разница: ' . $diff->days . ' дней, ' . $diff->m . ' месяцев'; 
Разница: 74 дней, 2 месяцев

Null-коалесценция при createFromFormat

Пример

$date = DateTime::createFromFormat('Y-m-d', $_GET['date'] ?? '') ?: null;
if ($date === null) {
    // обработка ошибки
}

создание объекта DateTime в PHP - comments

En
Php new datetime (php)