PHP 8.1.28 Released!

DateTimeImmutable::createFromFormat

date_create_immutable_from_format

(PHP 5 >= 5.5.0, PHP 7, PHP 8)

DateTimeImmutable::createFromFormat -- date_create_immutable_from_formatРазбирает строку с датой согласно указанному формату

Описание

Объектно-ориентированный стиль

public static DateTimeImmutable::createFromFormat(string $format, string $datetime, ?DateTimeZone $timezone = null): DateTimeImmutable|false

Процедурный стиль

Возвращает новый объект DateTimeImmutable, представляющий дату и время, указанные строкой в параметре datetime, которые были отформатированы в заданном формате format.

Список параметров

format

Формат даты и времени в виде строки (string), которому соответствует значение второго аргумента функции. Список вариантов форматирования представлен ниже. В большинстве случаев, при форматировании используются те же символы, что и в функции date().

Все поля инициализируются с текущей датой/временем. В большинстве случаев будет необходимо их "обнулить" (эпоха Unix, 1970-01-01 00:00:00 UTC). Для этого нужно добавить символ ! в качестве первого символа параметра format или | в качестве последнего. Для получения дополнительной информации смотрите документацию по каждому символу ниже.

Формат разбирается слева направо, это означает, что в некоторых ситуациях порядок присутствия символов формата влияет на результат. В случае z (день года) требуется, чтобы год уже был разобран, например, с помощью символов Y или y.

Символы для разбора чисел допускают широкий диапазон значений, выходящий за пределы логического диапазона. Например, d (день месяца) принимает значения в диапазоне от 00 до 99. Единственным ограничением является количество цифр. Когда задаются выходящие за пределы диапазона значения, срабатывает механизм переполнения анализатора даты/времени. Ниже показано несколько примеров такого поведения.

Это означает, что разобранные данные для буквы формата являются жадными и будут считываться до количества цифр, допускаемого форматом. Также это означает, что в строке datetime уже не хватает символов для следующих символов формата. Пример на этой странице также иллюстрирует эту проблему.

Список возможных символов для составления строки format
Символ в строке format Описание Возможные значения
День --- ---
d и j День месяца, 2 цифры с нулём в начале или без него От 01 до 31 либо от 1 до 31. (допускается использование двузначных чисел, превышающих количество дней в месяце, в этом случае разница переносится на следующий месяц. Например, использование числа 33 с январём означает 2 февраля)
D и l Текстовое представление дня недели От Mon до Sun либо от Sunday до Saturday. Если заданное имя дня отличается от имени дня, принадлежащего разобранной дате (или дате по умолчанию), то происходит переполнение до следующей даты с заданным именем дня. Смотрите примеры ниже для объяснения.
S Суффикс для числа в английской нумерации, 2 буквы. Эти буквы будут пропущены при разборе строки. st, nd, rd или th.
z Номер дня с начала года (начиная с 0); должно предшествовать Y или y. C 0 по 365. (Допускаются трёхзначные числа, превышающие числа в году, в этом случае разница переносится на следующий год. Например, использование числа 366 с 2022 годом означает 2 января 2023 года)
Месяц --- ---
F и M Текстовое представление месяца, например January или Sept С January по December либо с Jan по Dec
m и n Числовое представление месяца с первым нулём или без него С 01 по 12 либо с 1 по 12. (Допускаются двузначные числа больше 12, в этом случае разница переносится на следующий год. Например, использование числа 13 означает январь в следующем году)
Год --- ---
X и x Полное числовое представление года, до 19 цифр, с префиксом + или -. Примеры: 0055, 787, 1999, -2003, +10191
Y Полное числовое представление года, до 4 цифр. Примеры: 0055, 787, 1999, 2003.
y 2 цифры в представлении года (в диапазоне 1970-2069 включительно) Примеры: 99 или 03 (будет расшифровано как 1999 и 2003 соответственно)
Время --- ---
a и A До полудня и После полудня am или pm
g и h 12-ти часовой формат времени с первым нулём или без него С 1 по 12 либо с 01 по 12. (допускается использование двузначных чисел больше 12, в этом случае разница переносится на следующий день. Например, использование числа 14 означает 02 в следующем периоде AM/PM)
G и H 24-х часовой формат времени с нулём в начале или без него С 0 по 23 или с 00 по 23 (допускаются двузначные числа больше 24, в этом случае разница переносится на следующий день. Например, использование 26 означает 02:00 следующего дня)
i Минуты с нулём в начале С 00 по 59. (допускается использование двузначных чисел больше 59, в этом случае разница переносится на следующий час. Например, использование числа 66 означает :06 следующего часа)
s Секунды с нулём в начале От 00 до 59. (допускаются двузначные числа больше 59, в этом случае разница переносится на следующую минуту. Например, использование числа 90 означает :30 следующей минуты)
v Дробь в миллисекундах (до 3 цифр) Примеры: 12 (0.12 секунд), 345 (0.345 секунд)
u Дробь в микросекундах (до 6 цифр) Примеры: 45 (0.45 секунд), 654321 (0.654321 секунд)
Часовой пояс --- ---
e, O, P и T Идентификатор часового пояса, либо разница в часах относительно UTC, либо разница относительно UTC с двоеточием между часами и минутами, либо аббревиатура часового пояса Примеры: UTC, GMT, Atlantic/Azores или +0200 или +02:00 или EST, MDT
Дата/Время полностью --- ---
U Количество секунд с начала Эпохи Unix (January 1 1970 00:00:00 GMT) Пример: 1292177455
Пробел и Разделители --- ---
(пробел) Ноль или несколько символов пробела, табуляции, неразрывного пробела NBSP (U+A0) или узкого неразрывного пробела NNBSP (U+202F) Пример: "\t", " "
# Один из следующих символов: ;, :, /, ., ,, -, ( или ) Пример: /
;, :, /, ., ,, -, ( или ) Символ разделитель. Пример: -
? Один случайный (любой) символ Пример: ^ (Будьте внимательны: в UTF-8 кодировке вам может потребоваться более одного ?, так как там один символ может занимать более одного байта. В таких случаях может помочь использование *.
* Любое количество любых символов до следующего разделителя Пример: * в Y-*-d для строки 2009-aWord-08 будет соответствовать aWord
! Сбрасывает все поля (год, месяц, день, час, минута, секунда и часовой пояс) до нулевых значений (0 для часа, минуты, секунды, 1 для месяца и дня, 1970 для года и UTC для информации о часовом поясе). Без ! все поля будут соответствовать текущему времени.
| Сбрасывает значения незаданных полей (год, месяц, день, час, минута, секунда, часовой пояс) до нулевых значений. Y-m-d| установит год, месяц и день в соответствии с данными в строке, а часы, минуты и секунды установит в 0.
+ Если задан этот спецификатор, данные, завершающие строку (нуль байт например) не будут вызывать ошибку, только предупреждение Используйте DateTime::getLastErrors() для определения, были ли в строке завершающие символы.

Наличие в строке формата нераспознаваемых символов, отсутствующих в списке выше, приведёт к ошибке разбора строки. В этом случае сообщение об ошибке будет добавлено в возвращаемую структуру. Получить это сообщение можно с помощью функции DateTime::getLastErrors().

Для вставки в format буквенного символа, вы должны экранировать его с помощью обратного слеша(\).

Если format не содержит символ !, то значения полей, не заданных в строке формата, будут установлены в соответствии с текущим временем.

Если format содержит символ !, то значения полей, не заданных в строке формата (равно как и значения полей слева от !) будут установлены в соответствии со значениями полей начала Эпохи Unix.

Если любой символ времени разобран, то все остальные поля, связанные с временем, устанавливаются в "0", если они также не разобраны.

Начало эпохи Unix 1970-01-01 00:00:00 UTC.

datetime

Строка, представляющая время.

timezone

Объект класса DateTimeZone, представляющий ожидаемый часовой пояс.

Если timezone не указан или null и datetime не содержит часовой пояс, то будет использован текущий часовой пояс.

Замечание:

Параметр timezone и текущий часовой пояс будут проигнорированы, если параметр datetime также содержит метку времени UNIX (то есть timestamp вида 946684800) или же указанный часовой пояс (то есть 2010-01-28T15:00:00+02:00).

Возвращаемые значения

Возвращает новый экземпляр DateTimeImmutable или false, если возникла ошибка.

Ошибки

Функция выбрасывает ValueError, если параметр datetime содержит нулевые байты.

Список изменений

Версия Описание
8.2.9 Спецификатор (пробел) теперь также поддерживает символы неразрывного пробела NBSP (U+A0) и узкого неразрывного пробела NNBSP (U+202F).
8.2.0 Добавлены спецификаторы X и x параметру format.
8.0.21, 8.1.8, 8.2.0 Теперь, когда в параметр datetime передаются нулевые байты, выбрасывается исключение ValueError, ранее такая ситуация игнорировалась.
7.3.0 Добавлен спецификатор v параметру format.

Примеры

Пример #1 Пример использования DateTimeImmutable::createFromFormat()

Объектно-ориентированный стиль

<?php
$date
= DateTimeImmutable::createFromFormat('j-M-Y', '15-Feb-2009');
echo
$date->format('Y-m-d');
?>

Пример #2 Использование предопределённых констант формата с помощью DateTimeImmutable::createFromFormat()

Объектно-ориентированный стиль

<?php
$date
= DateTimeImmutable::createFromFormat(DateTimeInterface::ISO8601, '2004-02-12T15:19:21+00:00');
$date = DateTimeImmutable::createFromFormat(DateTimeInterface::RFC3339_EXTENDED, '2013-10-14T09:00:00.000+02:00');
?>

Константы форматирования, используемые в данном примере, состоят из строки символов для форматирования объекта DateTimeImmutable. В большинстве случаев эти буквы совпадают с теми же элементами информации о дате/времени, которые определены в параметрах выше, но они, как правило, более мягкие.

Пример #3 Тонкости DateTimeImmutable::createFromFormat()

<?php
echo 'Текущее время: ' . date('Y-m-d H:i:s') . "\n";

$format = 'Y-m-d';
$date = DateTimeImmutable::createFromFormat($format, '2009-02-15');
echo
"Формат: $format; " . $date->format('Y-m-d H:i:s') . "\n";

$format = 'Y-m-d H:i:s';
$date = DateTimeImmutable::createFromFormat($format, '2009-02-15 15:16:17');
echo
"Формат: $format; " . $date->format('Y-m-d H:i:s') . "\n";

$format = 'Y-m-!d H:i:s';
$date = DateTimeImmutable::createFromFormat($format, '2009-02-15 15:16:17');
echo
"Формат: $format; " . $date->format('Y-m-d H:i:s') . "\n";

$format = '!d';
$date = DateTimeImmutable::createFromFormat($format, '15');
echo
"Формат: $format; " . $date->format('Y-m-d H:i:s') . "\n";

$format = 'i';
$date = DateTimeImmutable::createFromFormat($format, '15');
echo
"Формат: $format; " . $date->format('Y-m-d H:i:s') . "\n";
?>

Вывод приведённого примера будет похож на:

Текущее время: 2022-06-02 15:50:46
Формат: Y-m-d; 2009-02-15 15:50:46
Формат: Y-m-d H:i:s; 2009-02-15 15:16:17
Формат: Y-m-!d H:i:s; 1970-01-15 15:16:17
Формат: !d; 1970-01-15 00:00:00
Формат: i; 2022-06-02 00:15:00

Пример #4 Форматирование строки с помощью литеральных символов

<?php
echo DateTimeImmutable::createFromFormat('H\h i\m s\s','23h 15m 03s')->format('H:i:s');
?>

Вывод приведённого примера будет похож на:

23:15:03

Пример #5 Поведение при переполнении

<?php
echo DateTimeImmutable::createFromFormat('Y-m-d H:i:s', '2021-17-35 16:60:97')->format(DateTimeImmutable::RFC2822);
?>

Вывод приведённого примера будет похож на:

Sat, 04 Jun 2022 17:01:37 +0000

Хотя результат выглядит странно, он правильный, так как случаются следующие переполнения:

  1. 97 секунд переваливают за 1 минуту, оставляя 37 секунд.
  2. 61 минут переваливает за 1 час, оставляя 1 минуту.
  3. 35 дней переваливают за 1 месяц, оставляя 4 дня. Количество оставшихся дней зависит от месяца, так как не в каждом месяце одинаковое количество дней.
  4. 18 месяцев переваливают за 1 год, оставляя 6 месяцев.

Пример #6 Поведение имени переполненного дня

<?php
$d
= DateTime::createFromFormat(DateTimeInterface::RFC1123, 'Mon, 3 Aug 2020 25:00:00 +0000');
echo
$d->format(DateTime::RFC1123), "\n";
?>

Вывод приведённого примера будет похож на:

Mon, 10 Aug 2020 01:00:00 +0000

Хотя результат выглядит странно, он правильный, так как случаются следующие переполнения:

  1. 3 Aug 2020 25:00:00 переваливает за (Tue) 4 Aug 2020 01:00.
  2. Применяется Mon, что переводит дату на Mon, 10 Aug 2020 01:00:00. Объяснение относительных ключевых слов, таких как Mon, описано в разделе относительные форматы.

Для обнаружения переполнений в датах можно использовать метод DateTimeImmutable::getLastErrors(), который будет включать предупреждение, если произошло переполнение.

Пример #7 Обнаружение переполнения дат

<?php
$d
= DateTimeImmutable::createFromFormat('Y-m-d H:i:s', '2021-17-35 16:60:97');
echo
$d->format(DateTimeImmutable::RFC2822), "\n\n";

var_dump(DateTimeImmutable::GetLastErrors());
?>

Вывод приведённого примера будет похож на:

Sat, 04 Jun 2022 17:01:37 +0000

array(4) {
  'warning_count' =>
  int(2)
  'warnings' =>
  array(1) {
    [19] =>
    string(27) "The parsed date was invalid"
  }
  'error_count' =>
  int(0)
  'errors' =>
  array(0) {
  }
}

Пример #8 Жадное поведение при разборе

<?php
print_r
(date_parse_from_format('Gis', '60101'));
?>

Вывод приведённого примера будет похож на:

Array
(
    [year] =>
    [month] =>
    [day] =>
    [hour] => 60
    [minute] => 10
    [second] => 0
    [fraction] => 0
    [warning_count] => 1
    [warnings] => Array
        (
            [5] => The parsed time was invalid
        )

    [error_count] => 1
    [errors] => Array
        (
            [4] => A two digit second could not be found
        )

    [is_localtime] =>
)

Формат G предназначен для разбора 24-часовых часов с ведущим нулём или без него. Для этого необходимо разобрать 1 или 2 цифры. Так как есть две следующие цифры, он жадно считывает это как 60.

Следующие символы формата i и s требуют двух цифр. Это означает, что 10 передаётся как минута (i) и что затем остаётся недостаточно цифр для разбора секунд (s).

На эту проблему указывает массив errors.

Кроме того, час 60 находится вне диапазона 0-24, что добавляет предупреждение в массив warnings о том, что время является недействительным.

Смотрите также

  • DateTimeImmutable::__construct() - Возвращает новый объект DateTimeImmutable
  • DateTimeImmutable::getLastErrors() - Возвращает предупреждения и ошибки
  • checkdate() - Проверяет корректность даты по григорианскому календарю
  • strptime() - Разбирает строку даты/времени, сгенерированную функцией strftime
add a note

User Contributed Notes 3 notes

up
1
Tessa at AuRiseCreative dot com
2 months ago
Since the description and examples don't exactly match for the timezone row, I want to clarify exactly which format each character outputs.

`e` outputs the timezone identifier, e.g. `America/New_York` or `Asia/Gaza`

`O` outputs the difference to UTC in hours, e.g. `-0500` or `+0200`

`P` outputs difference to UTC with a colon between hours and minutes, e.g. `-05:00` or `+02:00`

`T` outputs the timezone abbreviation, e.g. `EST` or `EET`
up
0
peter dot labos at gmail dot com
3 months ago
If you are not happy with wide range of conversions and repairs this method is making for you, or just want to check that date is really same as input:

```
$datetime = \DateTimeImmutable::createFromFormat('Y-m-d G:i:s', $userDateTimeInput);

if ($datetime && $datetime->format('Y-m-d G:i:s') === $userDateTimeInput) {
// $datetime is not false and we have a correct date in correct format from user
}
```
up
0
Andy Walker
1 year ago
To clarify, g/G are 12/24 hour time without a leading 0, and h/H are 12/24 hour time with a leading zero, as described here:

https://www.php.net/manual/en/datetime.format.php
To Top