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 ,
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
|
+ |
Если задали этот спецификатор, данные, которые завершают строку (например, NULL-байт), не будут вызывать ошибку, только предупреждение | Чтобы определить, были ли в строке завершающие символы, вызывают метод 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
содержит NULL-байты.
Версия | Описание |
---|---|
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";
$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
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
}
```