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
(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 |
Пробел и Разделители | --- | --- |
(пробел) |
Один пробел или один отступ табуляции | Пример: |
# |
Один из следующих символов: ; ,
: , / , . ,
, , - , ( или
)
|
Пример: / |
; ,
: , / , . ,
, , - , ( или
)
|
Символ разделитель. | Пример: - |
? |
Один случайный (любой) символ |
Пример: ^ (Будьте внимательны: в 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.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
о том, что время является недействительным.
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