reference/datetime/formats.xml
7a75b854c8c52226d38397e7e8177e339fdb273f
...
...
@@ -4,27 +4,147 @@
4
4
<title>Supported Date and Time Formats</title>
5
5

6
6
<para>
7
-
This section describes all the different formats that the
8
-
<function>strtotime</function>, <classname>DateTime</classname>
9
-
and <function>date_create</function> parser understands. The formats
10
-
are grouped by section. In most cases formats from different
11
-
sections can be used in the same date/time string. For each of
12
-
the supported formats, one or more examples are given, as well
7
+
This section describes all the different formats in a BNF-like format, that the
8
+
<classname>DateTimeImmutable</classname>, <classname>DateTime</classname>,
9
+
<function>date_create_immutable</function>,
10
+
<function>date_create</function>, <function>date_parse</function>, and
11
+
<function>strtotime</function> parser understands. The formats are grouped
12
+
by section. In most cases formats from different sections, separated by
13
+
whitespace, comma or dot, can be used in the same date/time string. For each
14
+
of the supported formats, one or more examples are given, as well
13
15
as a description for the format. Characters in single quotes in
14
16
the formats are case-insensitive (<literal>'t'</literal> could
15
17
be <literal>t</literal> or <literal>T</literal>), characters in
16
18
double quotes are case-sensitive (<literal>"T"</literal> is only
17
19
<literal>T</literal>).
18
20
</para>
21
+
<para>
22
+
To format <classname>DateTimeImmutable</classname> and
23
+
<classname>DateTime</classname> objects, please refer to the documentation
24
+
of the <function>DateTimeInterface::format</function> method.
25
+
</para>
26
+

27
+
<para>
28
+
A general set of rules should be taken into account.
29
+
</para>
30
+
<orderedlist>
31
+
<listitem>
32
+
<simpara>
33
+
The parser, allows for each unit (year, month, day, hour, minute, second)
34
+
the full range of values. For a year that's just 4 digits, for a month
35
+
that's 0-12, day is 0-31, hour is 0-24, and minute is 0-59.
36
+
</simpara>
37
+
</listitem>
38
+
<listitem>
39
+
<simpara>
40
+
60 is allowed for seconds, as sometimes date strings with that
41
+
leapsecond do show up. But PHP implements Unix time where "60" is not
42
+
a valid second number and hence it overflows.
43
+
</simpara>
44
+
</listitem>
45
+
<listitem>
46
+
<simpara>
47
+
<function>strtotime</function> returns &false; if any number is outside of
48
+
the ranges, and <function>DateTimeImmutable::__construct</function> throws
49
+
an exception.
50
+
</simpara>
51
+
</listitem>
52
+
<listitem>
53
+
<simpara>
54
+
If a string contains a date, all time elements are reset to 0.
55
+
</simpara>
56
+
</listitem>
57
+
<listitem>
58
+
<simpara>
59
+
All less-significant time elements are reset to 0 if any part of a time is
60
+
present in the given string.
61
+
</simpara>
62
+
</listitem>
63
+
<listitem>
64
+
<simpara>
65
+
The parser is dumb, and doesn't do any checks to make it faster (and
66
+
more generic).
67
+
</simpara>
68
+
</listitem>
69
+
<listitem>
70
+
<simpara>
71
+
Besides rules for individual time elements, the parser also understand
72
+
more specific <link linkend="datetime.formats.compound">compound
73
+
formats</link>, such as parsing Unix timestamps
74
+
(<literal>@1690388256</literal>) and ISO Weekdates
75
+
(<literal>2008-W28-3</literal>).
76
+
</simpara>
77
+
</listitem>
78
+
<listitem>
79
+
<para>
80
+
There is an additional check if an invalid date is provided:
81
+
<example>
82
+
<programlisting role="php">
83
+
<![CDATA[
84
+
<?php
85
+
$res = date_parse("2015-09-31");
86
+
var_dump($res["warnings"]);
87
+
?>
88
+
]]>
89
+
</programlisting>
90
+
&example.outputs;
91
+
<screen>
92
+
<![CDATA[
93
+
array(1) {
94
+
[11] =>
95
+
string(27) "The parsed date was invalid"
96
+
}
97
+
]]>
98
+
</screen>
99
+
</example>
100
+
</para>
101
+
</listitem>
102
+
<listitem>
103
+
<para>
104
+
It is already possible to handle the edge cases, but then
105
+
<function>DateTimeImmutable::createFromFormat</function> must be used
106
+
while supplying the correct format.
107
+
<example>
108
+
<programlisting role="php">
109
+
<![CDATA[
110
+
<?php
111
+
$res = DateTimeImmutable::createFromFormat("Y-m-d", "2015-09-34");
112
+
var_dump($res);
113
+
]]>
114
+
</programlisting>
115
+
&example.outputs;
116
+
<screen>
117
+
<![CDATA[
118
+
object(DateTimeImmutable)#1 (3) {
119
+
["date"]=>
120
+
string(26) "2015-10-04 17:24:43.000000"
121
+
["timezone_type"]=>
122
+
int(3)
123
+
["timezone"]=>
124
+
string(13) "Europe/London"
125
+
}
126
+
]]>
127
+
</screen>
128
+
</example>
129
+
</para>
130
+
</listitem>
131
+
</orderedlist>
19
132

20
133
<!--Time Formats: {{{-->
21
-
<sect1 xml:id="datetime.formats.time">
134
+
<sect1 annotations="chunk:false" xml:id="datetime.formats.time">
22
135
<title>Time Formats</title>
23
136

24
137
<para>
25
-
This page describes the different time formats that the
26
-
<function>strtotime</function>, <classname>DateTime</classname> and
27
-
<function>date_create</function> parser understands.
138
+
This page describes the different date/time formats in a BNF-like syntax,
139
+
that the <classname>DateTimeImmutable</classname>,
140
+
<classname>DateTime</classname>, <function>date_create</function>,
141
+
<function>date_create_immutable</function>, and
142
+
<function>strtotime</function> parser understands.
143
+
</para>
144
+
<para>
145
+
To format <classname>DateTimeImmutable</classname> and
146
+
<classname>DateTime</classname> objects, please refer to the documentation
147
+
of the <function>DateTimeInterface::format</function> method.
28
148
</para>
29
149

30
150
<table>
...
...
@@ -114,7 +234,7 @@
114
234
<entry>"4:08:37 am", "7:19:19P.M."</entry>
115
235
</row>
116
236
<row>
117
-
<entry>MS SQL (Hour, minutes, seconds and fraction with meridian), PHP 5.3 and later only</entry>
237
+
<entry>MS SQL (Hour, minutes, seconds and fraction with meridian)</entry>
118
238
<entry><literal>hh</literal> ":" <literal>MM</literal> ":" <literal>II</literal> [.:] [0-9]+ <literal>meridian</literal></entry>
119
239
<entry>"4:08:39:12313am"</entry>
120
240
</row>
...
...
@@ -175,13 +295,20 @@
175
295
<!--}}}-->
176
296

177
297
<!--Date Formats: {{{-->
178
-
<sect1 xml:id="datetime.formats.date">
298
+
<sect1 annotations="chunk:false" xml:id="datetime.formats.date">
179
299
<title>Date Formats</title>
180
300

181
301
<para>
182
-
This page describes the different date formats that the
183
-
<function>strtotime</function>, <classname>DateTime</classname> and
184
-
<function>date_create</function> parser understands.
302
+
This page describes the different date formats in a BNF-like syntax, that
303
+
the <classname>DateTimeImmutable</classname>,
304
+
<classname>DateTime</classname>, <function>date_create</function>,
305
+
<function>date_create_immutable</function>, and
306
+
<function>strtotime</function> parser understands.
307
+
</para>
308
+
<para>
309
+
To format <classname>DateTimeImmutable</classname> and
310
+
<classname>DateTime</classname> objects, please refer to the documentation
311
+
of the <function>DateTimeInterface::format</function> method.
185
312
</para>
186
313

187
314
<table>
...
...
@@ -250,6 +377,11 @@
250
377
<entry>[0-9]{4}</entry>
251
378
<entry>"2000", "2008", "1978"</entry>
252
379
</row>
380
+
<row>
381
+
<entry><literal>YYY</literal></entry>
382
+
<entry>[0-9]{5,19}</entry>
383
+
<entry>"81412", "20192"</entry>
384
+
</row>
253
385
</tbody>
254
386
</tgroup>
255
387
</table>
...
...
@@ -327,7 +459,7 @@
327
459
</row>
328
460
<row>
329
461
<entry>Day and textual month</entry>
330
-
<entry><literal>d</literal> ([ .\t-])* <literal>m</literal></entry>
462
+
<entry><literal>dd</literal> ([ .\t-])* <literal>m</literal></entry>
331
463
<entry>"1 July", "17 Apr", "9.May"</entry>
332
464
</row>
333
465
<row>
...
...
@@ -346,6 +478,11 @@
346
478
<entry>"1978", "2008"</entry>
347
479
</row>
348
480
<row>
481
+
<entry>Year (expanded, 5-19 digits with sign)</entry>
482
+
<entry>[+-] <literal>YYY</literal></entry>
483
+
<entry>"-81120", "+20192"</entry>
484
+
</row>
485
+
<row>
349
486
<entry>Textual month (and just the month)</entry>
350
487
<entry><literal>m</literal></entry>
351
488
<entry>"March", "jun", "DEC"</entry>
...
...
@@ -385,6 +522,11 @@
385
522
<entry>[+-]? <literal>YY</literal> "-" <literal>MM</literal> "-" <literal>DD</literal></entry>
386
523
<entry>"-0002-07-26", "+1978-04-17", "1814-05-17"</entry>
387
524
</row>
525
+
<row>
526
+
<entry>Five+ digit year with required sign, month and day</entry>
527
+
<entry>[+-] <literal>YYY</literal> "-" <literal>MM</literal> "-" <literal>DD</literal></entry>
528
+
<entry>"-81120-02-26", "+20192-04-17"</entry>
529
+
</row>
388
530
</tbody>
389
531
</tgroup>
390
532
</table>
...
...
@@ -420,7 +562,7 @@
420
562
</para>
421
563
</note>
422
564

423
-
<note>
565
+
<caution>
424
566
<para>
425
567
It is possible to over- and underflow the <literal>dd</literal> and
426
568
<literal>DD</literal> format. Day 0 means the last day of previous
...
...
@@ -429,7 +571,7 @@
429
571
to "2008-07-01" (June only has 30 days).
430
572
</para>
431
573
<para>
432
-
Note that as of PHP 5.1.0 the day range is restricted to 0-31 as indicated
574
+
Note that the day range is restricted to 0-31 as indicated
433
575
by the regular expression above. Thus "2008-06-32" is not a valid date
434
576
string, for instance.
435
577
</para>
...
...
@@ -447,18 +589,25 @@
447
589
"-0001-11-30" (the year -1 in the ISO 8601 calendar, which is 2 BC
448
590
in the proleptic Gregorian calendar).
449
591
</para>
450
-
</note>
592
+
</caution>
451
593
</sect1>
452
594
<!--}}}-->
453
595

454
596
<!--Compound Formats: {{{-->
455
-
<sect1 xml:id="datetime.formats.compound">
597
+
<sect1 annotations="chunk:false" xml:id="datetime.formats.compound">
456
598
<title>Compound Formats</title>
457
599

458
600
<para>
459
-
This page describes the different compound date/time formats that the
460
-
<function>strtotime</function>, <classname>DateTime</classname> and
461
-
<function>date_create</function> parser understands.
601
+
This page describes the different compound date/time formats in a BNF-like
602
+
syntax, that the <classname>DateTimeImmutable</classname>,
603
+
<classname>DateTime</classname>, <function>date_create</function>,
604
+
<function>date_create_immutable</function>, and
605
+
<function>strtotime</function> parser understands.
606
+
</para>
607
+
<para>
608
+
To format <classname>DateTimeImmutable</classname> and
609
+
<classname>DateTime</classname> objects, please refer to the documentation
610
+
of the <function>DateTimeInterface::format</function> method.
462
611
</para>
463
612

464
613
<table>
...
...
@@ -495,7 +644,7 @@
495
644
<row>
496
645
<entry><literal>HH</literal></entry>
497
646
<entry>[01][0-9] | "2"[0-4]</entry>
498
-
<entry>"04", "7", "19"</entry>
647
+
<entry>"04", "07", "19"</entry>
499
648
</row>
500
649
<row>
501
650
<entry><literal>meridian</literal></entry>
...
...
@@ -504,7 +653,7 @@
504
653
</row>
505
654
<row>
506
655
<entry><literal>ii</literal></entry>
507
-
<entry>[0-5][0-9]</entry>
656
+
<entry>[0-5]?[0-9]</entry>
508
657
<entry>"04", "8", "59"</entry>
509
658
</row>
510
659
<row>
...
...
@@ -529,8 +678,8 @@
529
678
</row>
530
679
<row>
531
680
<entry><literal>ss</literal></entry>
532
-
<entry>[0-5][0-9]</entry>
533
-
<entry>"04", "8", "59"</entry>
681
+
<entry>([0-5]?[0-9])|60</entry>
682
+
<entry>"04", "8", "59", "60" (leap second)</entry>
534
683
</row>
535
684
<row>
536
685
<entry><literal>SS</literal></entry>
...
...
@@ -557,6 +706,72 @@
557
706
</table>
558
707

559
708
<table>
709
+
<title>Standards Formats</title>
710
+
<tgroup cols="2">
711
+
<thead>
712
+
<row>
713
+
<entry>Description</entry>
714
+
<entry>Examples</entry>
715
+
</row>
716
+
</thead>
717
+
<tbody>
718
+
<row>
719
+
<entry>ATOM</entry>
720
+
<entry>"2022-06-02T16:58:35+00:00"</entry>
721
+
</row>
722
+
<row>
723
+
<entry>COOKIE</entry>
724
+
<entry>"Thursday, 02-Jun-2022 16:58:35 UTC"</entry>
725
+
</row>
726
+
<row>
727
+
<entry>ISO8601</entry>
728
+
<entry>"2022-06-02T16:58:35+0000"</entry>
729
+
</row>
730
+
<row>
731
+
<entry><link xlink:href="&url.rfc;822">RFC 822</link></entry>
732
+
<entry>"Thu, 02 Jun 22 16:58:35 +0000"</entry>
733
+
</row>
734
+
<row>
735
+
<entry><link xlink:href="&url.rfc;850">RFC 850</link></entry>
736
+
<entry>"Thursday, 02-Jun-22 16:58:35 UTC"</entry>
737
+
</row>
738
+
<row>
739
+
<entry><link xlink:href="&url.rfc;1036">RFC 1036</link></entry>
740
+
<entry>"Thu, 02 Jun 22 16:58:35 +0000"</entry>
741
+
</row>
742
+
<row>
743
+
<entry><link xlink:href="&url.rfc;1123">RFC 1123</link></entry>
744
+
<entry>"Thu, 02 Jun 2022 16:58:35 +0000"</entry>
745
+
</row>
746
+
<row>
747
+
<entry><link xlink:href="&url.rfc;2822">RFC 2822</link></entry>
748
+
<entry>"Thu, 02 Jun 2022 16:58:35 +0000"</entry>
749
+
</row>
750
+
<row>
751
+
<entry><link xlink:href="&url.rfc;3339">RFC 3339</link></entry>
752
+
<entry>"2022-06-02T16:58:35+00:00"</entry>
753
+
</row>
754
+
<row>
755
+
<entry><link xlink:href="&url.rfc;3339">RFC 3339</link> Extended</entry>
756
+
<entry>"2022-06-02T16:58:35.698+00:00"</entry>
757
+
</row>
758
+
<row>
759
+
<entry><link xlink:href="&url.rfc;7231">RFC 7231</link></entry>
760
+
<entry>"Thu, 02 Jun 2022 16:58:35 GMT"</entry>
761
+
</row>
762
+
<row>
763
+
<entry>RSS</entry>
764
+
<entry>"Thu, 02 Jun 2022 16:58:35 +0000"</entry>
765
+
</row>
766
+
<row>
767
+
<entry>W3C</entry>
768
+
<entry>"2022-06-02T16:58:35+00:00"</entry>
769
+
</row>
770
+
</tbody>
771
+
</tgroup>
772
+
</table>
773
+

774
+
<table>
560
775
<title>Localized Notations</title>
561
776
<tgroup cols="3">
562
777
<thead>
...
...
@@ -608,6 +823,11 @@
608
823
<entry>"@1215282385"</entry>
609
824
</row>
610
825
<row>
826
+
<entry>Unix Timestamp with microseconds</entry>
827
+
<entry>"@" "-"? [0-9]+ "." [0-9]{0,6}</entry>
828
+
<entry>"@1607974647.503686"</entry>
829
+
</row>
830
+
<row>
611
831
<entry>XMLRPC</entry>
612
832
<entry><literal>YY</literal> <literal>MM</literal> <literal>DD</literal> "T" <literal>hh</literal> ":" <literal>II</literal> ":" <literal>SS</literal></entry>
613
833
<entry>"20080701T22:38:07", "20080701T9:38:07"</entry>
...
...
@@ -633,7 +853,7 @@
633
853
"W".
634
854
</para>
635
855
<para>
636
-
The "T" in the SOAP, XMRPC and WDDX formats is case-sensitive, you
856
+
The "T" in the SOAP, XMLRPC and WDDX formats is case-sensitive, you
637
857
can only use the upper case "T".
638
858
</para>
639
859
<para>
...
...
@@ -644,12 +864,19 @@
644
864
<!--}}}-->
645
865

646
866
<!--Relative Formats: {{{-->
647
-
<sect1 xml:id="datetime.formats.relative">
867
+
<sect1 annotations="chunk:false" xml:id="datetime.formats.relative">
648
868
<title>Relative Formats</title>
649
869
<para>
650
-
This page describes the different relative date/time formats that the
651
-
<function>strtotime</function>, <classname>DateTime</classname> and
652
-
<function>date_create</function> parser understands.
870
+
This page describes the different relative date/time formats in a BNF-like
871
+
syntax, that the <classname>DateTimeImmutable</classname>,
872
+
<classname>DateTime</classname>, <function>date_create</function>,
873
+
<function>date_create_immutable</function>, and
874
+
<function>strtotime</function> parser understands.
875
+
</para>
876
+
<para>
877
+
To format <classname>DateTimeImmutable</classname> and
878
+
<classname>DateTime</classname> objects, please refer to the documentation
879
+
of the <function>DateTimeInterface::format</function> method.
653
880
</para>
654
881

655
882
<table>
...
...
@@ -692,9 +919,10 @@
692
919
</row>
693
920
<row>
694
921
<entry><literal>unit</literal></entry>
695
-
<entry>(('sec' | 'second' | 'min' | 'minute' | 'hour' | 'day' |
696
-
'fortnight' | 'forthnight' | 'month' | 'year') 's'?) | 'weeks' |
697
-
<literal>daytext</literal></entry>
922
+
<entry>'ms' | 'µs' | (( 'msec' | 'millisecond' | 'µsec' | 'microsecond'
923
+
| 'usec' | 'sec' | 'second' | 'min' | 'minute' | 'hour' | 'day' |
924
+
'fortnight' | 'forthnight' | 'month' | 'year') 's'?) | 'weeks' |
925
+
<literal>daytext</literal></entry>
698
926
</row>
699
927
</tbody>
700
928
</tgroup>
...
...
@@ -754,13 +982,15 @@
754
982
<row>
755
983
<entry>'first day of'</entry>
756
984
<entry>Sets the day of the first of the current month. This phrase is
757
-
best used together with a month name following it.</entry>
985
+
usually best used together with a month name following it as it only
986
+
effects the current month</entry>
758
987
<entry>"first day of January 2008"</entry>
759
988
</row>
760
989
<row>
761
990
<entry>'last day of'</entry>
762
991
<entry>Sets the day to the last day of the current month. This phrase is
763
-
best used together with a month name following it.</entry>
992
+
usually best used together with a month name following it as it only
993
+
effects the current month</entry>
764
994
<entry>"last day of next month"</entry>
765
995
</row>
766
996
<row>
...
...
@@ -779,9 +1009,12 @@
779
1009
<entry>"+5 weeks", "12 day", "-7 weekdays"</entry>
780
1010
</row>
781
1011
<row>
782
-
<entry><literal>ordinal</literal> <literal>space</literal> <literal>unit</literal></entry>
783
-
<entry>Handles relative time items where the value is text.</entry>
784
-
<entry>"fifth day", "second month"</entry>
1012
+
<entry>(<literal>ordinal</literal> | <literal>reltext</literal>) <literal>space</literal> <literal>unit</literal></entry>
1013
+
<entry>Handles relative time items where the value is text.
1014
+
<literal>last</literal> and <literal>previous</literal> are equivalent
1015
+
to <literal>-1</literal>, <literal>this</literal> to nothing, and
1016
+
<literal>next</literal> to <literal>+1</literal>.</entry>
1017
+
<entry>"fifth day", "second month", "last day", "previous year"</entry>
785
1018
</row>
786
1019
<row>
787
1020
<entry>'ago'</entry>
...
...
@@ -790,7 +1023,10 @@
790
1023
</row>
791
1024
<row>
792
1025
<entry><literal>dayname</literal></entry>
793
-
<entry>Moves to the next day of this name.</entry>
1026
+
<entry>
1027
+
Moves to the next day of this name. (See <link
1028
+
linkend="datetime.formats.relative.dayname-note">note</link>)
1029
+
</entry>
794
1030
<entry>"Monday"</entry>
795
1031
</row>
796
1032
<row>
...
...
@@ -816,10 +1052,18 @@
816
1052
produces "2008-07-24 00:00". The reason for this is that those
817
1053
five statements directly influence the current time.
818
1054
</para>
1055
+
<para>
1056
+
Keywords such as "first day of" depend on the context in which the
1057
+
relative format string is used. If used with a static method or function,
1058
+
the referent is the current system timestamp. However, if used in
1059
+
<function>DateTime::modify</function> or
1060
+
<function>DateTimeImmutable::modify</function>, the referent is the object
1061
+
on which the <literal>modify()</literal> method is called.
1062
+
</para>
819
1063
</note>
820
1064

821
1065
<note>
822
-
<para>
1066
+
<para xml:id="datetime.formats.relative.dayname-note">
823
1067
Observe the following remarks when the current day-of-week is the
824
1068
same as the day-of-week used in the date/time string. The current
825
1069
day-of-week could have been (re-)calculated by non-relative parts of
...
...
@@ -930,6 +1174,14 @@
930
1174
December being 31 days in length, producing a total of 61 days.
931
1175
</para>
932
1176
</note>
1177
+
<note>
1178
+
<para>
1179
+
<literal>number</literal> is an <emphasis>integer</emphasis> number; if a
1180
+
decimal number is given, the dot (or comma) is likely interpreted as delimiter.
1181
+
For instance, <literal>'+1.5 hours'</literal> is parsed like
1182
+
<literal>'+1 5 hours'</literal>, not as <literal>'+1 hour +30 minutes'</literal>.
1183
+
</para>
1184
+
</note>
933
1185

934
1186
<sect2 role="changelog">
935
1187
&reftitle.changelog;
...
...
@@ -944,17 +1196,17 @@
944
1196
</thead>
945
1197
<tbody>
946
1198
<row>
947
-
<entry>5.6.23, 7.0.8</entry>
1199
+
<entry>8.2.0</entry>
948
1200
<entry>
949
-
Weeks always start on monday. Formerly, sunday would also be considered
950
-
to start a week.
1201
+
<literal>number</literal> no longer accepts multiple signs,
1202
+
e.g. <literal>+-2</literal>.
951
1203
</entry>
952
1204
</row>
953
-
<row>
954
-
<entry>5.3.3</entry>
1205
+
<row>
1206
+
<entry>7.0.8</entry>
955
1207
<entry>
956
-
"first day" and "last day" changed to behave has "+1 day" and "-1 day",
957
-
respectively. Previously, the behaviour was as "first day of" and "last day of".
1208
+
Weeks always start on monday. Formerly, sunday would also be considered
1209
+
to start a week.
958
1210
</entry>
959
1211
</row>
960
1212
</tbody>
961
1213