(PHP 5 >= 5.5.0, PHP 7, PHP 8)
DateTimeImmutable::createFromFormat --date_create_immutable_from_format —Parses a time string according to a specified format
Object-oriented style
$format
,string$datetime
,?DateTimeZone$timezone
=null
):DateTimeImmutable|falseProcedural style
$format
,string$datetime
,?DateTimeZone$timezone
=null
):DateTimeImmutable|false Returns a new DateTimeImmutable object representing the date and time specified by thedatetime
string, which was formatted in the givenformat
.
format
The format that the passed instring should be in. See the formatting options below. In most cases, the same letters as for thedate() can be used.
All fields are initialised with the current date/time. In most cases you would want to reset these to "zero" (the Unix epoch,1970-01-01 00:00:00 UTC
). You do that by including the!
character as first character in yourformat
, or|
as your last. Please see the documentation for each character below for more information.
The format is parsed from left to right, which means that in some situations the order in which the format characters are present affects the result. In the case ofz
(the day of the year), it is required that a year has already been parsed, for example through theY
ory
characters.
Letters that are used for parsing numbers allow a wide range of values, outside of what the logical range would be. For example, thed
(day of the month) accepts values in the range from00
to99
. The only constraint is on the amount of digits. The date/time parser's overflow mechanism is used when out-of-range values are given. The examples below show some of this behaviour.
This also means that the data parsed for a format letter is greedy, and will read up to the amount of digits its format allows for. That can then also mean that there are no longer enough characters in thedatetime
string for following format characters. An example on this page also illustrates this issue.
format character | Description | Example parsable values |
---|---|---|
Day | --- | --- |
d andj | Day of the month, 2 digits with or without leading zeros | 01 to31 or1 to31 . (2 digit numbers higher than the number of days in the month are accepted, in which case they will make the month overflow. For example using 33 with January, means February 2nd) |
D andl | A textual representation of a day | Mon throughSun orSunday throughSaturday . If the day name given is different then the day name belonging to a parsed (or default) date is different, then an overflow occurs to thenext date with the given day name. See the examples below for an explanation. |
S | English ordinal suffix for the day of the month, 2 characters. It's ignored while processing. | st ,nd ,rd orth . |
z | The day of the year (starting from 0); must be preceded byY ory . | 0 through365 . (3 digit numbers higher than the numbers in a year are accepted, in which case they will make the year overflow. For example using 366 with 2022, means January 2nd, 2023) |
Month | --- | --- |
F andM | A textual representation of a month, such as January or Sept | January throughDecember orJan throughDec |
m andn | Numeric representation of a month, with or without leading zeros | 01 through12 or1 through12 . (2 digit numbers higher than 12 are accepted, in which case they will make the year overflow. For example using 13 means January in the next year) |
Year | --- | --- |
X andx | A full numeric representation of a year, up to 19 digits, optionally prefixed by+ or- | Examples:0055 ,787 ,1999 ,-2003 ,+10191 |
Y | A full numeric representation of a year, up to 4 digits | Examples:0055 ,787 ,1999 ,2003 |
y | A two digit representation of a year (which is assumed to be in the range 1970-2069, inclusive) | Examples:99 or03 (which will be interpreted as1999 and2003 , respectively) |
Time | --- | --- |
a andA | Ante meridiem and Post meridiem | am orpm |
g andh | 12-hour format of an hour with or without leading zero | 1 through12 or01 through12 (2 digit numbers higher than 12 are accepted, in which case they will make the day overflow. For example using14 means02 in the next AM/PM period) |
G andH | 24-hour format of an hour with or without leading zeros | 0 through23 or00 through23 (2 digit numbers higher than 24 are accepted, in which case they will make the day overflow. For example using26 means02:00 the next day) |
i | Minutes with leading zeros | 00 to59 . (2 digit numbers higher than 59 are accepted, in which case they will make the hour overflow. For example using66 means:06 the next hour) |
s | Seconds, with leading zeros | 00 through59 (2 digit numbers higher than 59 are accepted, in which case they will make the minute overflow. For example using90 means:30 the next minute) |
v | Fraction in milliseconds (up to three digits) | Example:12 (0.12 seconds),345 (0.345 seconds) |
u | Fraction in microseconds (up to six digits) | Example:45 (0.45 seconds),654321 (0.654321 seconds) |
Timezone | --- | --- |
e ,O ,p ,P andT | Timezone identifier, or difference to UTC in hours, or difference to UTC with colon between hours and minutes, or timezone abbreviation | Examples:UTC ,GMT ,Atlantic/Azores or+0200 or+02:00 orEST ,MDT |
Full Date/Time | --- | --- |
U | Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT) | Example:1292177455 |
Whitespace and Separators | --- | --- |
(space) | Zero or more spaces, tabs, NBSP (U+A0), or NNBSP (U+202F) characters | Example:"\t" ," " |
# | One of the following separation symbol:; ,: ,/ ,. ,, ,- ,( or) | Example:/ |
; ,: ,/ ,. ,, ,- ,( or) | The specified character. | Example:- |
? | A random byte | Example:^ (Be aware that for UTF-8 characters you might need more than one? . In this case, using* is probably what you want instead) |
* | Random bytes until the next separator or digit | Example:* inY-*-d with the string2009-aWord-08 will matchaWord |
! | Resets all fields (year, month, day, hour, minute, second, fraction and timezone information) to zero-like values (0 for hour, minute, second and fraction,1 for month and day,1970 for year andUTC for timezone information) | Without!, all fields will be set to the current date and time. |
| | Resets all fields (year, month, day, hour, minute, second, fraction and timezone information) to zero-like values if they have not been parsed yet | Y-m-d| will set the year, month and day to the information found in the string to parse, and sets the hour, minute and second to 0. |
+ | If this format specifier is present, trailing data in the string will not cause an error, but a warning instead | UseDateTimeImmutable::getLastErrors() to find out whether trailing data was present. |
Unrecognized characters in the format string will cause the parsing to fail and an error message is appended to the returned structure. You can query error messages withDateTimeImmutable::getLastErrors().
To include literal characters informat
, you have to escape them with a backslash (\
).
Ifformat
does not contain the character!
then portions of the generated date/time which are not specified informat
will be set to the current system time.
Ifformat
contains the character!
, then portions of the generated date/time not provided informat
, as well as values to the left-hand side of the!
, will be set to corresponding values from the Unix epoch.
If any time character is parsed, then all other time-related fields are set to "0", unless also parsed.
The Unix epoch is 1970-01-01 00:00:00 UTC.
datetime
String representing the time.
timezone
ADateTimeZone object representing the desired time zone.
Iftimezone
is omitted ornull
anddatetime
contains no timezone, the current timezone will be used.
Note:
The
timezone
parameter and the current timezone are ignored when thedatetime
parameter either contains a UNIX timestamp (e.g.946684800
) or specifies a timezone (e.g.2010-01-28T15:00:00+02:00
).
Returns a new DateTimeImmutable instance orfalse
on failure.
This method throwsValueError when thedatetime
contains NULL-bytes.
Version | Description |
---|---|
8.2.9 | The (space) specifier now also supports NBSP (U+A0) and NNBSP (U+202F) characters. |
8.2.0 | TheX andx format specifiers have been added. |
8.0.21, 8.1.8, 8.2.0 | Now throwsValueError when NULL-bytes are passed intodatetime , which previously was silently ignored. |
7.3.0 | Thev format specifier has been added. |
Example #1DateTimeImmutable::createFromFormat() example
Object-oriented style
<?php
$date=DateTimeImmutable::createFromFormat('j-M-Y','15-Feb-2009');
echo$date->format('Y-m-d');
?>
Example #2 Using predefined format constants withDateTimeImmutable::createFromFormat()
Object-oriented style
<?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');
?>
Theformatting constants as used in this example consist of a string of characters forformatting aDateTimeImmutable object. In most cases, these letters match with the same elements of date/time information as the ones defined in theparameters section above, but they tend to be more lenient.
Example #3 Intricacies ofDateTimeImmutable::createFromFormat()
<?php
echo'Current time: '.date('Y-m-d H:i:s') ."\n";
$format='Y-m-d';
$date=DateTimeImmutable::createFromFormat($format,'2009-02-15');
echo"Format:$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:$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:$format; ".$date->format('Y-m-d H:i:s') ."\n";
$format='!d';
$date=DateTimeImmutable::createFromFormat($format,'15');
echo"Format:$format; ".$date->format('Y-m-d H:i:s') ."\n";
$format='i';
$date=DateTimeImmutable::createFromFormat($format,'15');
echo"Format:$format; ".$date->format('Y-m-d H:i:s') ."\n";
?>
The above example will outputsomething similar to:
Current time: 2022-06-02 15:50:46Format: Y-m-d; 2009-02-15 15:50:46Format: Y-m-d H:i:s; 2009-02-15 15:16:17Format: Y-m-!d H:i:s; 1970-01-15 15:16:17Format: !d; 1970-01-15 00:00:00Format: i; 2022-06-02 00:15:00
Example #4 Format string with literal characters
<?php
echoDateTimeImmutable::createFromFormat('H\h i\m s\s','23h 15m 03s')->format('H:i:s');
?>
The above example will outputsomething similar to:
23:15:03
Example #5 Overflow behaviour
<?php
echoDateTimeImmutable::createFromFormat('Y-m-d H:i:s','2021-17-35 16:60:97')->format(DateTimeImmutable::RFC2822);
?>
The above example will outputsomething similar to:
Sat, 04 Jun 2022 17:01:37 +0000
Although the result looks odd, it is correct, as the following overflows happen:
97
seconds overflows to1
minute, leaving37
seconds.61
minutes overflows to1
hour, leaving1
minutes.35
days overflows to1
month, leaving4
days. The amount of days that are left over depends on the month, as not every month has the same amount of days.18
months overflows to1
year, leaving6
months.Example #6 Overflowing day name behaviour
<?php
$d=DateTime::createFromFormat(DateTimeInterface::RFC1123,'Mon, 3 Aug 2020 25:00:00 +0000');
echo$d->format(DateTime::RFC1123),"\n";
?>
The above example will outputsomething similar to:
Mon, 10 Aug 2020 01:00:00 +0000
Although the result looks odd, it is correct, as the following overflows happen:
3 Aug 2020 25:00:00
overflows to(Tue) 4 Aug 2020 01:00
.Mon
gets applied, which advances the date toMon, 10 Aug 2020 01:00:00
. The explanation of relative keywords such asMon
is explained in the section onrelative formats.In order to detect overflows in dates, you can useDateTimeImmutable::getLastErrors(), which will include a warning if an overflow occured.
Example #7 Detecting overflown dates
<?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());
?>
The above example will outputsomething similar to:
Sat, 04 Jun 2022 17:01:37 +0000array(4) { 'warning_count' => int(2) 'warnings' => array(1) { [19] => string(27) "The parsed date was invalid" } 'error_count' => int(0) 'errors' => array(0) { }}
Example #8 Greedy parsing behaviour
<?php
print_r(date_parse_from_format('Gis','60101'));
?>
The above example will outputsomething similar to:
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] =>)
TheG
format is to parse 24 hour clock hours, with or without leading zero. This requires to parse 1 or 2 digits. Because there are two following digits, it greedily reads this as60
.
The followingi
ands
format characters both require two digits. This means that10
is passed as minute (i
), and that there are then not enough digits left to parse for as second (s
).
Theerrors
array indicates this problem.
Additionally, an hour of60
is outside the range0
-24
, which causes thewarnings
array to include a warning that the time is invalid.
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`
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
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
}
```