(PHP 5 >= 5.5.0, PHP 7, PHP 8)
DateTimeImmutable::createFromFormat -- date_create_immutable_from_format — Разбирает строку с датой согласно указанному формату
Объектно-ориентированный стиль
$format
, string$datetime
, ?DateTimeZone$timezone
= null
): DateTimeImmutable|falseПроцедурный стиль
$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 | Описание | Возможные значения |
---|---|---|
День | --- | --- |
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
Хотя результат выглядит странно, он правильный, так как случаются следующие переполнения:
97
секунд переваливают за 1
минуту, оставляя 37
секунд. 61
минут переваливает за 1
час, оставляя 1
минуту. 35
дней переваливают за 1
месяц, оставляя 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
Хотя результат выглядит странно, он правильный, так как случаются следующие переполнения:
3 Aug 2020 25:00:00
переваливает за (Tue) 4 Aug 2020 01:00
. 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
о том, что время является недействительным.