This section describes all the different formats in a BNF-like format, that the
DateTimeImmutable, DateTime,
date_create_immutable(),
date_create(), date_parse(), and
strtotime() parser understands. The formats are grouped
by section. In most cases formats from different sections, separated by
whitespace, comma or dot, can be used in the same date/time string. For each
of the supported formats, one or more examples are given, as well
as a description for the format. Characters in single quotes in
the formats are case-insensitive ('t' could
be t or T), characters in
double quotes are case-sensitive ("T" is only
T).
A general set of rules should be taken into account.
The parser, allows for each unit (year, month, day, hour, minute, second)
the full range of values. For a year that's just 4 digits, for a month
that's 0-12, day is 0-31, hour is 0-24, and minute is 0-59.
60 is allowed for seconds, as sometimes date strings with that
leapsecond do show up. But PHP implements Unix time where "60" is not
a valid second number and hence it overflows.
If a string contains a date, all time elements are reset to 0.
All less-significant time elements are reset to 0 if any part of a time is
present in the given string.
The parser is dumb, and doesn't do any checks to make it faster (and
more generic).
Besides rules for individual time elements, the parser also understand
more specific compound
formats, such as parsing Unix timestamps
(@1690388256) and ISO Weekdates
(2008-W28-3).
There is an additional check if an invalid date is provided:
Day, month and four digit year, with dots, tabs or dashes
dd [.\t-] mm [.-] YY
"30-6-2008", "22.12.1978"
Day, month and two digit year, with dots or tabs
dd [.\t] mm "." yy
"30.6.08", "22\t12.78"
Day, textual month and year
dd ([ \t.-])* m ([ \t.-])* y
"30-June 2008", "22DEC78", "14 III 1879"
Textual month and four digit year (Day reset to 1)
m ([ \t.-])* YY
"June 2008", "DEC1978", "March 1879"
Four digit year and textual month (Day reset to 1)
YY ([ \t.-])* m
"2008 June", "1978-XII", "1879.MArCH"
Textual month, day and year
m ([ .\t-])* dd [,.stndrh\t ]+ y
"July 1st, 2008", "April 17, 1790", "May.9,78"
Textual month and day
m ([ .\t-])* dd [,.stndrh\t ]*
"July 1st,", "Apr 17", "May.9"
Day and textual month
dd ([ .\t-])* m
"1 July", "17 Apr", "9.May"
Month abbreviation, day and year
M "-" DD "-" y
"May-09-78", "Apr-17-1790"
Year, month abbreviation and day
y "-" M "-" DD
"78-Dec-22", "1814-MAY-17"
Year (and just the year)
YY
"1978", "2008"
Year (expanded, 5-19 digits with sign)
[+-] YYY
"-81120", "+20192"
Textual month (and just the month)
m
"March", "jun", "DEC"
ISO8601 Notations
Description
Format
Examples
Eight digit year, month and day
YYMMDD
"15810726", "19780417", "18140517"
Four digit year, month and day with slashes
YY "/" MM "/" DD
"2008/06/30", "1978/12/22"
Two digit year, month and day with dashes
yy "-" MM "-" DD
"08-06-30", "78-12-22"
Four digit year with optional sign, month and day
[+-]? YY "-" MM "-" DD
"-0002-07-26", "+1978-04-17", "1814-05-17"
Five+ digit year with required sign, month and day
[+-] YYY "-" MM "-" DD
"-81120-02-26", "+20192-04-17"
Note:
For the y and yy
formats, years below 100 are handled in a special way when the
y or yy symbol is used.
If the year falls in the range 0 (inclusive) to 69 (inclusive),
2000 is added. If the year falls in the range 70 (inclusive) to
99 (inclusive) then 1900 is added. This means that "00-01-01" is
interpreted as "2000-01-01".
Note:
The "Day, month and two digit year, with dots or tabs" format
(dd [.\t] mm "."
yy) only works for the year values 61 (inclusive)
to 99 (inclusive) - outside those years the time
format "HH [.:] MM
[.:] SS" has precedence.
Note:
The "Year (and just the year)" format only reliably works if a time string
has already been found. Otherwise, if the four digit year matches
HHMM then these two date elements
are set instead.
It is possible to over- and underflow the dd and
DD format. Day 0 means the last day of previous
month, whereas overflows count into the next month. This makes
"2008-08-00" equivalent to "2008-07-31" and "2008-06-31" equivalent
to "2008-07-01" (June only has 30 days).
Note that the day range is restricted to 0-31 as indicated
by the regular expression above. Thus "2008-06-32" is not a valid date
string, for instance.
It is also possible to underflow the mm and
MM formats with the value 0. A month value of
0 means December of the previous year. As example "2008-00-22" is
equivalent to "2007-12-22".
If you combine the previous two facts and underflow both the day and
the month, the following happens: "2008-00-00" first gets converted
to "2007-12-00" which then gets converted to "2007-11-30". This also
happens with the string "0000-00-00", which gets transformed into
"-0001-11-30" (the year -1 in the ISO 8601 calendar, which is 2 BC
in the proleptic Gregorian calendar).
Sets the day of the first of the current month. This phrase is
usually best used together with a month name following it as it only
effects the current month
"first day of January 2008"
'last day of'
Sets the day to the last day of the current month. This phrase is
usually best used together with a month name following it as it only
effects the current month
"last day of next month"
ordinalspacedaynamespace 'of'
Calculates the x-th week day of the current month.
"first sat of July 2008"
'last' spacedaynamespace 'of'
Calculates the last week day of the current month.
"last sat of July 2008"
numberspace? (unit | 'week')
Handles relative time items where the value is a number.
"+5 weeks", "12 day", "-7 weekdays"
(ordinal | reltext) spaceunit
Handles relative time items where the value is text.
last and previous are equivalent
to -1, this to nothing, and
next to +1.
Handles the special format "weekday + last/this/next week".
"Monday next week"
Note:
Relative statements are always processed after
non-relative statements. This makes "+1 week july 2008" and "july
2008 +1 week" equivalent.
Exceptions to this rule are: "yesterday", "midnight", "today", "noon"
and "tomorrow". Note that "tomorrow 11:00" and "11:00 tomorrow"
are different. Considering today's date of "July 23rd, 2008" the
first one produces "2008-07-24 11:00" where as the second one
produces "2008-07-24 00:00". The reason for this is that those
five statements directly influence the current time.
Keywords such as "first day of" depend on the context in which the
relative format string is used. If used with a static method or function,
the referent is the current system timestamp. However, if used in
DateTime::modify() or
DateTimeImmutable::modify(), the referent is the object
on which the modify() method is called.
Note:
Observe the following remarks when the current day-of-week is the
same as the day-of-week used in the date/time string. The current
day-of-week could have been (re-)calculated by non-relative parts of
the date/time string however.
"dayname" does not advance to
another day. (Example: "Wed July 23rd, 2008" means "2008-07-23").
"numberdayname" does
not advance to another day. (Example: "1
wednesday july 23rd, 2008" means "2008-07-23").
"number week dayname" will
first add the number of weeks, but does not
advance to another day. In this case "number
week" and "dayname" are two distinct blocks.
(Example: "+1 week wednesday july 23rd, 2008" means "2008-07-30").
"ordinaldayname"
does advance to another day. (Example "first
wednesday july 23rd, 2008" means "2008-07-30").
"number week ordinaldayname" will first add the number of
weeks, and then advances to another
day. In this case "number week" and
"ordinaldayname" are two
distinct blocks. (Example: "+1 week first wednesday july 23rd,
2008" means "2008-08-06").
"ordinaldayname 'of' "
does not advance to another day. (Example:
"first wednesday of july 23rd, 2008" means "2008-07-02" because
the specific phrase with 'of' resets the day-of-month to '1' and
the '23rd' is ignored here).
Also observe that the "of" in "ordinalspacedaynamespace 'of' " and "'last' spacedaynamespace 'of' " does
something special.
It sets the day-of-month to 1.
"ordinaldayname 'of' " does
not advance to another day. (Example: "first
tuesday of july 2008" means "2008-07-01").
"ordinaldayname "
does advance to another day. (Example: "first
tuesday july 2008" means "2008-07-08", see also point 4 in the
list above).
"'last' dayname 'of' " takes the last
dayname of the current month. (Example: "last
wed of july 2008" means "2008-07-30")
"'last' dayname" takes the last
dayname from the current day. (Example: "last
wed july 2008" means "2008-06-25"; "july 2008" first sets the
current date to "2008-07-01" and then "last wed" moves to the
previous Wednesday which is "2008-06-25").
Note:
Relative month values are calculated based on the length of months that
they pass through. An example would be "+2 month 2011-11-30", which would
produce "2012-01-30". This is due to November being 30 days in length, and
December being 31 days in length, producing a total of 61 days.
Note:
number is an integer number; if a
decimal number is given, the dot (or comma) is likely interpreted as delimiter.
For instance, '+1.5 hours' is parsed like
'+1 5 hours', not as '+1 hour +30 minutes'.
Changelog
Version
Description
8.4.0
number now again accepts a plus sign followed by a
minus sign, e.g. +-2, and other combinations of
multiple signs.
8.2.0
number no longer accepts a plus sign followed by a
minus sign, e.g. +-2.
7.0.8
Weeks always start on monday. Formerly, sunday would also be considered
to start a week.