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
,
сбрасывают до начальных значений Unix-эпохи путём включения в начало строки формата
символа !
или в конец строки формата символа |
.
Подробнее о работе символов рассказывает документация к каждому параметру в таблице ниже.
Метод анализирует формат слева направо, поэтому в отдельных случаях порядок
расположения символов формата влияет на результат. Методу вначале требуется
проанализировать год, например, через символы Y
или y
,
если строка формата содержит символ z
, для которого метод ищет день года.
Символы для разбора чисел допускают широкий диапазон значений,
который выходит за пределы логического диапазона. Например,
символ 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
|
От 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 |
Двузначное представление года в диапазоне 1970-2069 включительно |
Примеры:
99 или 03 ,
которые метод интерпретирует как 1999
и 2003
|
Время | --- | --- |
a и A |
Ante meridiem (лат. «до полудня») или Post meridiem (лат. «после полудня») |
Регистронезависимые обозначения 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 ,
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
|
! |
Сбрасывает поля «год», «месяц», «день», «час», «минута»,
«секунда», «милли-» или «микросекунда» и «часовой пояс»
до начальных значений Unix-эпохи: 0 для часа, минуты и секунды,
1 для месяца и дня, 1970 для года
и UTC для информации о часовом поясе
|
Без символа ! метод установит полям
текущие дату и время системы
|
| |
Сбрасывает значения полей «год», «месяц», «день», «час», «минута», «секунда», «милли-» или «микросекунда» и «часовой пояс», которые метод ещё не разобрал, до начальных значений Unix-эпохи |
Формат Y-m-d| установит год, месяц и день на основе информации,
которую нашёл в строке для разбора, а для часа, минуты и секунды установит значение 0
|
+ |
С этим спецификатором формата лишние данные в конце строки разбора, добавят в структуру, которую создаёт метод, не ошибку, а предупреждение | Содержала ли строка разбора в конце лишние данные, покажет метод DateTime::getLastErrors() |
Символы в строке формата, которые метод не распознал, вызовут сбой разбора, и метод добавит в структуру с предупреждениями и ошибками, которую он создаёт, сообщение об ошибке. Сообщения об ошибке запрашивают методом DateTime::getLastErrors().
При включении в строку формата format
буквальных символов,
символы экранируют обратным слешем: \
.
Метод сгенерирует дату и время на основе информации в строке разбора,
а частям даты и времени, которые не указали в строке формата format
,
установит текущее время системы, если строка формата format
не содержит символ !
.
Метод сгенерирует дату и время на основе информации в строке разбора,
а частям даты и времени, которые не указали в строке формата format
,
и значениям слева от символа !
установит значения даты и времени начала Unix-эпохи,
если строка формата format
содержит символ !
.
Метод установит нулевые значения остальным полям времени, которые не указали в строке формата, если разобрал хотя бы один символ для поля времени.
Начало эпохи Unix — 1970-01-01 00:00:00 UTC.
datetime
Строка, которая представляет время.
timezone
Объект класса DateTimeZone, который представляет часовой пояс.
Метод установит текущий часовой пояс, если часовой пояс
timezone
опустили или установили для параметра значение null
,
а дата и время datetime
не содержит часового пояса.
Замечание:
Метод проигнорирует параметр
timezone
и текущий часовой пояс, если параметрdatetime
либо содержит метку времени UNIX наподобие946684800
, либо указывает часовой пояс наподобие2010-01-28T15:00:00+02:00
.
Метод возвращает новый экземпляр класса DateTimeImmutable или false
, если возникла ошибка.
Метод выбрасывает исключение ValueError,
если параметр datetime
содержит NUL-байты.
Версия | Описание |
---|---|
8.2.9 |
Спецификатор (пробел) теперь также поддерживает символы
неразрывного пробела NBSP
(U+A0) и узкого неразрывного пробела NNBSP (U+202F).
|
8.2.0 |
Добавили спецификаторы X и x
для параметра format .
|
8.0.21, 8.1.8, 8.2.0 |
Теперь метод выбрасывает исключение ValueError,
если в параметр datetime передали NULL-байты,
что раньше метод без предупреждения игнорировал.
|
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";
/**
* Метод распознает каждое поле в строке разбора,
* а затем сбросит поля «год» и «месяц» на начальные значения даты и времени Unix-эпохи,
* поскольку эти параметры оказались слева от символа «!» в строке формата,
* а поля «день», «час», «минута» и «секунда» сохранят значения, которые получили из строки разбора,
* поскольку эти параметры оказались справа от символа «!» и метод распознал для них значения;
* дробная часть времени со значением долей секунды вернёт значение 000000, поскольку метод
* не разобрал ни милли-, ни микросекунды, а другие поля времени при этом указали
*/
$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.u') . "\n";
/**
* Метод заполнит поле «день» значением «15», поскольку в строке формата указали символ дня
* и метод распознал в строке разбора значение для этого параметра,
* а остальные поля даты и времени метод сбросит на начальные значения
* даты и времени эпохи Unix, поскольку для этих полей не указали
* параметры и значения в строках формата и разбора
*/
$format = '!d';
$date = DateTimeImmutable::createFromFormat($format, '15');
echo "Формат: $format; " . $date->format('Y-m-d H:i:s') . "\n";
/**
* Метод заполнит поле «минуты» значением 15,
* поскольку распознал в строке разбора значение для символа минут i.
* Поля «год», «месяц» и «день» получат значения системной даты,
* поскольку метод не разобрал эти поля в строках формата и разбора, а в строке формата
* не было символов «!» или «|», при которых год, месяц и день получили бы значения начала Unix-эпохи.
* А остальным полям времени метод установит нулевые значения,
* поскольку метод не нашёл эти параметры и значения для них в строках формата и разбора,
* но методу удалось разобрать хотя бы одно временно́е поле
*/
$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 цифры. Поскольку строка формата первым содержит параметр G,
и строка разбора в начале содержит две цифры,
которые идут одна за другой, метод жадно считывает значение часа как 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
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`
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
}
```