reference/datetime/datetimeimmutable/createfromformat.xml
280c1486811039092af54aa172a05417372bebb9
...
...
@@ -10,25 +10,784 @@
10
10
<refsect1 role="description">
11
11
&reftitle.description;
12
12
<para>&style.oop;</para>
13
-
<methodsynopsis role="oop">
13
+
<methodsynopsis role="DateTimeImmutable">
14
14
<modifier>public</modifier> <modifier>static</modifier> <type class="union"><type>DateTimeImmutable</type><type>false</type></type><methodname>DateTimeImmutable::createFromFormat</methodname>
15
15
<methodparam><type>string</type><parameter>format</parameter></methodparam>
16
16
<methodparam><type>string</type><parameter>datetime</parameter></methodparam>
17
17
<methodparam choice="opt"><type class="union"><type>DateTimeZone</type><type>null</type></type><parameter>timezone</parameter><initializer>&null;</initializer></methodparam>
18
18
</methodsynopsis>
19
19
<para>&style.procedural;</para>
20
-
<methodsynopsis role="procedural">
20
+
<methodsynopsis>
21
21
<type class="union"><type>DateTimeImmutable</type><type>false</type></type><methodname>date_create_immutable_from_format</methodname>
22
22
<methodparam><type>string</type><parameter>format</parameter></methodparam>
23
23
<methodparam><type>string</type><parameter>datetime</parameter></methodparam>
24
24
<methodparam choice="opt"><type class="union"><type>DateTimeZone</type><type>null</type></type><parameter>timezone</parameter><initializer>&null;</initializer></methodparam>
25
25
</methodsynopsis>
26
26
<para>
27
-
Like <methodname>DateTime::createFromFormat</methodname> but works with
28
-
<classname>DateTimeImmutable</classname>.
27
+
Returns a new DateTimeImmutable object representing the date and time specified by the
28
+
<parameter>datetime</parameter> string, which was formatted in the given
29
+
<parameter>format</parameter>.
29
30
</para>
30
31
</refsect1>
31
32

33
+
<refsect1 role="parameters" xml:id="datetimeimmutable.createfromformat.parameters">
34
+
&reftitle.parameters;
35
+
<variablelist>
36
+
<varlistentry>
37
+
<term><parameter>format</parameter></term>
38
+
<listitem>
39
+
<para>
40
+
The format that the passed in <type>string</type> should be in. See the
41
+
formatting options below. In most cases, the same letters as for the
42
+
<function>date</function> can be used.
43
+
</para>
44
+
<para>
45
+
All fields are initialised with the current date/time. In most cases you
46
+
would want to reset these to "zero" (the Unix epoch, <literal>1970-01-01
47
+
00:00:00 UTC</literal>). You do that by including the
48
+
<literal>!</literal> character as first character in your
49
+
<parameter>format</parameter>, or <literal>|</literal> as your last.
50
+
Please see the documentation for each character below for more
51
+
information.
52
+
</para>
53
+
<para>
54
+
The format is parsed from left to right, which means that in some
55
+
situations the order in which the format characters are present affects
56
+
the result. In the case of <literal>z</literal> (the day of the year),
57
+
it is required that a year has already been parsed,
58
+
for example through the <literal>Y</literal> or <literal>y</literal>
59
+
characters.
60
+
</para>
61
+
<para>
62
+
Letters that are used for parsing numbers allow a wide range of values,
63
+
outside of what the logical range would be. For example, the
64
+
<literal>d</literal> (day of the month) accepts values in the range from
65
+
<literal>00</literal> to <literal>99</literal>. The only constraint is
66
+
on the amount of digits. The date/time parser's overflow mechanism is
67
+
used when out-of-range values are given. The examples below show some of
68
+
this behaviour.
69
+
</para>
70
+
<para>
71
+
This also means that the data parsed for a format letter is greedy, and
72
+
will read up to the amount of digits its format allows for. That can
73
+
then also mean that there are no
74
+
longer enough characters in the <parameter>datetime</parameter> string
75
+
for following format characters. An example on this page also
76
+
illustrates this issue.
77
+
</para>
78
+
<para>
79
+
<table>
80
+
<title>The following characters are recognized in the
81
+
<parameter>format</parameter> parameter string</title>
82
+
<tgroup cols="3">
83
+
<thead>
84
+
<row>
85
+
<entry><parameter>format</parameter> character</entry>
86
+
<entry>Description</entry>
87
+
<entry>Example parsable values</entry>
88
+
</row>
89
+
</thead>
90
+
<tbody>
91
+
<row>
92
+
<entry align="center"><emphasis>Day</emphasis></entry>
93
+
<entry>---</entry>
94
+
<entry>---</entry>
95
+
</row>
96
+
<row>
97
+
<entry><literal>d</literal> and <literal>j</literal></entry>
98
+
<entry>Day of the month, 2 digits with or without leading zeros</entry>
99
+
<entry>
100
+
<literal>01</literal> to <literal>31</literal> or
101
+
<literal>1</literal> to <literal>31</literal>. (2 digit numbers
102
+
higher than the number of days in the month are accepted, in which
103
+
case they will make the month overflow. For example using 33 with
104
+
January, means February 2nd)
105
+
</entry>
106
+
</row>
107
+
<row>
108
+
<entry><literal>D</literal> and <literal>l</literal></entry>
109
+
<entry>A textual representation of a day</entry>
110
+
<entry>
111
+
<literal>Mon</literal> through <literal>Sun</literal> or
112
+
<literal>Sunday</literal> through <literal>Saturday</literal>. If
113
+
the day name given is different then the day name belonging to a
114
+
parsed (or default) date is different, then an overflow occurs to
115
+
the <emphasis>next</emphasis> date with the given day name. See the
116
+
examples below for an explanation.
117
+
</entry>
118
+
</row>
119
+
<row>
120
+
<entry><literal>S</literal></entry>
121
+
<entry>English ordinal suffix for the day of the month, 2
122
+
characters. It's ignored while processing.</entry>
123
+
<entry>
124
+
<literal>st</literal>, <literal>nd</literal>, <literal>rd</literal> or
125
+
<literal>th</literal>.
126
+
</entry>
127
+
</row>
128
+
<row>
129
+
<entry><literal>z</literal></entry>
130
+
<entry>
131
+
The day of the year (starting from 0);
132
+
must be preceded by <literal>Y</literal> or <literal>y</literal>.
133
+
</entry>
134
+
<entry>
135
+
<literal>0</literal> through <literal>365</literal>. (3 digit
136
+
numbers higher than the numbers in a year are accepted, in which
137
+
case they will make the year overflow. For example using 366 with
138
+
2022, means January 2nd, 2023)
139
+
</entry>
140
+
</row>
141
+
<row>
142
+
<entry align="center"><emphasis>Month</emphasis></entry>
143
+
<entry>---</entry>
144
+
<entry>---</entry>
145
+
</row>
146
+
<row>
147
+
<entry><literal>F</literal> and <literal>M</literal></entry>
148
+
<entry>A textual representation of a month, such as January or Sept</entry>
149
+
<entry>
150
+
<literal>January</literal> through <literal>December</literal> or
151
+
<literal>Jan</literal> through <literal>Dec</literal>
152
+
</entry>
153
+
</row>
154
+
<row>
155
+
<entry><literal>m</literal> and <literal>n</literal></entry>
156
+
<entry>Numeric representation of a month, with or without leading zeros</entry>
157
+
<entry>
158
+
<literal>01</literal> through <literal>12</literal> or
159
+
<literal>1</literal> through <literal>12</literal>.
160
+
(2 digit numbers higher than 12 are accepted, in which case they
161
+
will make the year overflow. For example using 13 means January in
162
+
the next year)
163
+
</entry>
164
+
</row>
165
+
<row>
166
+
<entry align="center"><emphasis>Year</emphasis></entry>
167
+
<entry>---</entry>
168
+
<entry>---</entry>
169
+
</row>
170
+
<row>
171
+
<entry><literal>X</literal> and <literal>x</literal></entry>
172
+
<entry>A full numeric representation of a year, up to 19 digits,
173
+
optionally prefixed by <literal>+</literal> or
174
+
<literal>-</literal></entry>
175
+
<entry>Examples: <literal>0055</literal>, <literal>787</literal>,
176
+
<literal>1999</literal>, <literal>-2003</literal>,
177
+
<literal>+10191</literal></entry>
178
+
</row>
179
+
<row>
180
+
<entry><literal>Y</literal></entry>
181
+
<entry>A full numeric representation of a year, up to 4 digits</entry>
182
+
<entry>Examples: <literal>0055</literal>, <literal>787</literal>,
183
+
<literal>1999</literal>, <literal>2003</literal></entry>
184
+
</row>
185
+
<row>
186
+
<entry><literal>y</literal></entry>
187
+
<entry>
188
+
A two digit representation of a year (which is assumed to be in the
189
+
range 1970-2069, inclusive)
190
+
</entry>
191
+
<entry>
192
+
Examples:
193
+
<literal>99</literal> or <literal>03</literal>
194
+
(which will be interpreted as <literal>1999</literal> and
195
+
<literal>2003</literal>, respectively)
196
+
</entry>
197
+
</row>
198
+
<row>
199
+
<entry align="center"><emphasis>Time</emphasis></entry>
200
+
<entry>---</entry>
201
+
<entry>---</entry>
202
+
</row>
203
+
<row>
204
+
<entry><literal>a</literal> and <literal>A</literal></entry>
205
+
<entry>Ante meridiem and Post meridiem</entry>
206
+
<entry><literal>am</literal> or <literal>pm</literal></entry>
207
+
</row>
208
+
<row>
209
+
<entry><literal>g</literal> and <literal>h</literal></entry>
210
+
<entry>12-hour format of an hour with or without leading zero</entry>
211
+
<entry>
212
+
<literal>1</literal> through <literal>12</literal> or
213
+
<literal>01</literal> through <literal>12</literal> (2 digit
214
+
numbers higher than 12 are accepted, in which case they will make
215
+
the day overflow. For example using <literal>14</literal> means
216
+
<literal>02</literal> in the next AM/PM period)
217
+
</entry>
218
+
</row>
219
+
<row>
220
+
<entry><literal>G</literal> and <literal>H</literal></entry>
221
+
<entry>24-hour format of an hour with or without leading zeros</entry>
222
+
<entry>
223
+
<literal>0</literal> through <literal>23</literal> or
224
+
<literal>00</literal> through <literal>23</literal> (2 digit
225
+
numbers higher than 24 are accepted, in which case they will make
226
+
the day overflow. For example using <literal>26</literal> means
227
+
<literal>02:00</literal> the next day)
228
+
</entry>
229
+
</row>
230
+
<row>
231
+
<entry><literal>i</literal></entry>
232
+
<entry>Minutes with leading zeros</entry>
233
+
<entry>
234
+
<literal>00</literal> to <literal>59</literal>. (2 digit
235
+
numbers higher than 59 are accepted, in which case they will make
236
+
the hour overflow. For example using <literal>66</literal> means
237
+
<literal>:06</literal> the next hour)
238
+
</entry>
239
+
</row>
240
+
<row>
241
+
<entry><literal>s</literal></entry>
242
+
<entry>Seconds, with leading zeros</entry>
243
+
<entry>
244
+
<literal>00</literal> through <literal>59</literal> (2 digit
245
+
numbers higher than 59 are accepted, in which case they will make
246
+
the minute overflow. For example using <literal>90</literal> means
247
+
<literal>:30</literal> the next minute)
248
+
</entry>
249
+
</row>
250
+
<row>
251
+
<entry><literal>v</literal></entry>
252
+
<entry>Fraction in milliseconds (up to three digits)</entry>
253
+
<entry>Example: <literal>12</literal> (<literal>0.12</literal>
254
+
seconds), <literal>345</literal> (<literal>0.345</literal> seconds)</entry>
255
+
</row>
256
+
<row>
257
+
<entry><literal>u</literal></entry>
258
+
<entry>Fraction in microseconds (up to six digits)</entry>
259
+
<entry>Example: <literal>45</literal> (<literal>0.45</literal>
260
+
seconds), <literal>654321</literal> (<literal>0.654321</literal>
261
+
seconds)</entry>
262
+
</row>
263
+
<row>
264
+
<entry align="center"><emphasis>Timezone</emphasis></entry>
265
+
<entry>---</entry>
266
+
<entry>---</entry>
267
+
</row>
268
+
<row>
269
+
<entry>
270
+
<literal>e</literal>, <literal>O</literal>,
271
+
<literal>P</literal> and <literal>T</literal>
272
+
</entry>
273
+
<entry>Timezone identifier, or difference to UTC in hours, or
274
+
difference to UTC with colon between hours and minutes, or timezone
275
+
abbreviation</entry>
276
+
<entry>Examples: <literal>UTC</literal>, <literal>GMT</literal>,
277
+
<literal>Atlantic/Azores</literal> or
278
+
<literal>+0200</literal> or <literal>+02:00</literal> or
279
+
<literal>EST</literal>, <literal>MDT</literal>
280
+
</entry>
281
+
</row>
282
+
<row>
283
+
<entry align="center"><emphasis>Full Date/Time</emphasis></entry>
284
+
<entry>---</entry>
285
+
<entry>---</entry>
286
+
</row>
287
+
<row>
288
+
<entry><literal>U</literal></entry>
289
+
<entry>Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)</entry>
290
+
<entry>Example: <literal>1292177455</literal></entry>
291
+
</row>
292
+
<row>
293
+
<entry align="center"><emphasis>Whitespace and Separators</emphasis></entry>
294
+
<entry>---</entry>
295
+
<entry>---</entry>
296
+
</row>
297
+
<row>
298
+
<entry><literal> </literal> (space)</entry>
299
+
<entry>Zero or more spaces, tabs, NBSP (U+A0), or NNBSP (U+202F)
300
+
characters</entry>
301
+
<entry>Example: <literal>"\t"</literal>, <literal>" "</literal></entry>
302
+
</row>
303
+
<row>
304
+
<entry><literal>#</literal></entry>
305
+
<entry>
306
+
One of the following separation symbol: <literal>;</literal>,
307
+
<literal>:</literal>, <literal>/</literal>, <literal>.</literal>,
308
+
<literal>,</literal>, <literal>-</literal>, <literal>(</literal> or
309
+
<literal>)</literal>
310
+
</entry>
311
+
<entry>Example: <literal>/</literal></entry>
312
+
</row>
313
+
<row>
314
+
<entry>
315
+
<literal>;</literal>,
316
+
<literal>:</literal>, <literal>/</literal>, <literal>.</literal>,
317
+
<literal>,</literal>, <literal>-</literal>, <literal>(</literal> or
318
+
<literal>)</literal>
319
+
</entry>
320
+
<entry>The specified character.</entry>
321
+
<entry>Example: <literal>-</literal></entry>
322
+
</row>
323
+
<row>
324
+
<entry><literal>?</literal></entry>
325
+
<entry>A random byte</entry>
326
+
<entry>Example: <literal>^</literal> (Be aware that for UTF-8
327
+
characters you might need more than one <literal>?</literal>.
328
+
In this case, using <literal>*</literal> is probably what you want
329
+
instead)</entry>
330
+
</row>
331
+
<row>
332
+
<entry><literal>*</literal></entry>
333
+
<entry>Random bytes until the next separator or digit</entry>
334
+
<entry>Example: <literal>*</literal> in <literal>Y-*-d</literal> with
335
+
the string <literal>2009-aWord-08</literal> will match
336
+
<literal>aWord</literal></entry>
337
+
</row>
338
+
<row>
339
+
<entry><literal>!</literal></entry>
340
+
<entry>Resets all fields (year, month, day, hour, minute, second,
341
+
fraction and timezone information) to zero-like values (
342
+
<literal>0</literal> for hour, minute, second and fraction,
343
+
<literal>1</literal> for month and day, <literal>1970</literal>
344
+
for year and <literal>UTC</literal> for timezone information)</entry>
345
+
<entry>Without <literal>!,</literal> all fields will be set to the
346
+
current date and time.</entry>
347
+
</row>
348
+
<row>
349
+
<entry><literal>|</literal></entry>
350
+
<entry>Resets all fields (year, month, day, hour, minute, second,
351
+
fraction and timezone information) to zero-like values if they have
352
+
not been parsed yet</entry>
353
+
<entry><literal>Y-m-d|</literal> will set the year, month and day
354
+
to the information found in the string to parse, and sets the hour,
355
+
minute and second to 0.</entry>
356
+
</row>
357
+
<row>
358
+
<entry><literal>+</literal></entry>
359
+
<entry>If this format specifier is present, trailing data in the
360
+
string will not cause an error, but a warning instead</entry>
361
+
<entry>Use <methodname>DateTimeImmutable::getLastErrors</methodname> to find out
362
+
whether trailing data was present.</entry>
363
+
</row>
364
+
</tbody>
365
+
</tgroup>
366
+
</table>
367
+
</para>
368
+
<para>
369
+
Unrecognized characters in the format string will cause the
370
+
parsing to fail and an error message is appended to the returned
371
+
structure. You can query error messages with
372
+
<methodname>DateTimeImmutable::getLastErrors</methodname>.
373
+
</para>
374
+
<para>
375
+
To include literal characters in <parameter>format</parameter>, you have
376
+
to escape them with a backslash (<literal>\</literal>).
377
+
</para>
378
+
<para>
379
+
If <parameter>format</parameter> does not contain the character
380
+
<literal>!</literal> then portions of the generated date/time which are not
381
+
specified in <parameter>format</parameter> will be set to the current
382
+
system time.
383
+
</para>
384
+
<para>
385
+
If <parameter>format</parameter> contains the
386
+
character <literal>!</literal>, then portions of the generated
387
+
date/time not provided in <parameter>format</parameter>, as well as
388
+
values to the left-hand side of the <literal>!</literal>, will
389
+
be set to corresponding values from the Unix epoch.
390
+
</para>
391
+
<para>
392
+
If any time character is parsed, then all other time-related fields are
393
+
set to "0", unless also parsed.
394
+
</para>
395
+
<para>
396
+
The Unix epoch is 1970-01-01 00:00:00 UTC.
397
+
</para>
398
+
</listitem>
399
+
</varlistentry>
400
+
<varlistentry>
401
+
<term><parameter>datetime</parameter></term>
402
+
<listitem>
403
+
<para>
404
+
String representing the time.
405
+
</para>
406
+
</listitem>
407
+
</varlistentry>
408
+
<varlistentry>
409
+
<term><parameter>timezone</parameter></term>
410
+
<listitem>
411
+
<para>
412
+
A <classname>DateTimeZone</classname> object representing the
413
+
desired time zone.
414
+
</para>
415
+
<para>
416
+
If <parameter>timezone</parameter> is omitted or &null; and
417
+
<parameter>datetime</parameter> contains no timezone,
418
+
the current timezone will be used.
419
+
</para>
420
+
<note>
421
+
<para>
422
+
The <parameter>timezone</parameter> parameter
423
+
and the current timezone are ignored when the
424
+
<parameter>datetime</parameter> parameter either
425
+
contains a UNIX timestamp (e.g. <literal>946684800</literal>)
426
+
or specifies a timezone
427
+
(e.g. <literal>2010-01-28T15:00:00+02:00</literal>).
428
+
</para>
429
+
</note>
430
+
</listitem>
431
+
</varlistentry>
432
+
</variablelist>
433
+
</refsect1>
434
+

435
+
<refsect1 role="returnvalues">
436
+
&reftitle.returnvalues;
437
+
<para>
438
+
Returns a new DateTimeImmutable instance&return.falseforfailure;.
439
+
</para>
440
+
</refsect1>
441
+

442
+
<refsect1 role="errors">
443
+
&reftitle.errors;
444
+
<para>
445
+
This method throws <exceptionname>ValueError</exceptionname> when the
446
+
<parameter>datetime</parameter> contains NULL-bytes.
447
+
</para>
448
+
</refsect1>
449
+

450
+
<refsect1 role="changelog">
451
+
&reftitle.changelog;
452
+
<para>
453
+
<informaltable>
454
+
<tgroup cols="2">
455
+
<thead>
456
+
<row>
457
+
<entry>&Version;</entry>
458
+
<entry>&Description;</entry>
459
+
</row>
460
+
</thead>
461
+
<tbody>
462
+
<row>
463
+
<entry>8.2.9</entry>
464
+
<entry>
465
+
The <literal> </literal> (space) specifier now also supports NBSP
466
+
(U+A0) and NNBSP (U+202F) characters.
467
+
</entry>
468
+
</row>
469
+
<row>
470
+
<entry>8.2.0</entry>
471
+
<entry>
472
+
The <literal>X</literal> and <literal>x</literal>
473
+
<parameter>format</parameter> specifiers have been added.
474
+
</entry>
475
+
</row>
476
+
<row>
477
+
<entry>8.0.21, 8.1.8, 8.2.0</entry>
478
+
<entry>
479
+
Now throws <exceptionname>ValueError</exceptionname> when NULL-bytes
480
+
are passed into <parameter>datetime</parameter>, which previously was silently
481
+
ignored.
482
+
</entry>
483
+
</row>
484
+
<row>
485
+
<entry>7.3.0</entry>
486
+
<entry>
487
+
The <literal>v</literal> <parameter>format</parameter> specifier has
488
+
been added.
489
+
</entry>
490
+
</row>
491
+
</tbody>
492
+
</tgroup>
493
+
</informaltable>
494
+
</para>
495
+
</refsect1>
496
+

497
+
<refsect1 role="examples">
498
+
&reftitle.examples;
499
+
<example>
500
+
<title><function>DateTimeImmutable::createFromFormat</function> example</title>
501
+
<para>&style.oop;</para>
502
+
<programlisting role="php">
503
+
<![CDATA[
504
+
<?php
505
+
$date = DateTimeImmutable::createFromFormat('j-M-Y', '15-Feb-2009');
506
+
echo $date->format('Y-m-d');
507
+
?>
508
+
]]>
509
+
</programlisting>
510
+
</example>
511
+

512
+
<example>
513
+
<title>Using predefined format constants with <function>DateTimeImmutable::createFromFormat</function></title>
514
+
<para>&style.oop;</para>
515
+
<programlisting role="php">
516
+
<![CDATA[
517
+
<?php
518
+
$date = DateTimeImmutable::createFromFormat(DateTimeInterface::ISO8601, '2004-02-12T15:19:21+00:00');
519
+
$date = DateTimeImmutable::createFromFormat(DateTimeInterface::RFC3339_EXTENDED, '2013-10-14T09:00:00.000+02:00');
520
+
?>
521
+
]]>
522
+
</programlisting>
523
+
<para>
524
+
The <link linkend="datetimeinterface.constants.types">formatting constants</link>
525
+
as used in this example consist of
526
+
a string of characters for <link linkend="datetime.format">formatting</link> a
527
+
<classname>DateTimeImmutable</classname> object. In most cases, these
528
+
letters match with the same elements of date/time information as the ones defined in the <link
529
+
linkend="datetimeimmutable.createfromformat.parameters">parameters</link>
530
+
section above, but they tend to be more lenient.
531
+
</para>
532
+
</example>
533
+

534
+
<example>
535
+
<title>Intricacies of <function>DateTimeImmutable::createFromFormat</function></title>
536
+
<programlisting role="php">
537
+
<![CDATA[
538
+
<?php
539
+
echo 'Current time: ' . date('Y-m-d H:i:s') . "\n";
540
+

541
+
$format = 'Y-m-d';
542
+
$date = DateTimeImmutable::createFromFormat($format, '2009-02-15');
543
+
echo "Format: $format; " . $date->format('Y-m-d H:i:s') . "\n";
544
+

545
+
$format = 'Y-m-d H:i:s';
546
+
$date = DateTimeImmutable::createFromFormat($format, '2009-02-15 15:16:17');
547
+
echo "Format: $format; " . $date->format('Y-m-d H:i:s') . "\n";
548
+

549
+
$format = 'Y-m-!d H:i:s';
550
+
$date = DateTimeImmutable::createFromFormat($format, '2009-02-15 15:16:17');
551
+
echo "Format: $format; " . $date->format('Y-m-d H:i:s') . "\n";
552
+

553
+
$format = '!d';
554
+
$date = DateTimeImmutable::createFromFormat($format, '15');
555
+
echo "Format: $format; " . $date->format('Y-m-d H:i:s') . "\n";
556
+

557
+
$format = 'i';
558
+
$date = DateTimeImmutable::createFromFormat($format, '15');
559
+
echo "Format: $format; " . $date->format('Y-m-d H:i:s') . "\n";
560
+
?>
561
+
]]>
562
+
</programlisting>
563
+
&example.outputs.similar;
564
+
<screen>
565
+
<![CDATA[
566
+
Current time: 2022-06-02 15:50:46
567
+
Format: Y-m-d; 2009-02-15 15:50:46
568
+
Format: Y-m-d H:i:s; 2009-02-15 15:16:17
569
+
Format: Y-m-!d H:i:s; 1970-01-15 15:16:17
570
+
Format: !d; 1970-01-15 00:00:00
571
+
Format: i; 2022-06-02 00:15:00
572
+
]]>
573
+
</screen>
574
+
</example>
575
+

576
+
<example>
577
+
<title>Format string with literal characters</title>
578
+
<programlisting role="php">
579
+
<![CDATA[
580
+
<?php
581
+
echo DateTimeImmutable::createFromFormat('H\h i\m s\s','23h 15m 03s')->format('H:i:s');
582
+
?>
583
+
]]>
584
+
</programlisting>
585
+
&example.outputs.similar;
586
+
<screen>
587
+
<![CDATA[
588
+
23:15:03
589
+
]]>
590
+
</screen>
591
+
</example>
592
+

593
+
<example>
594
+
<title>Overflow behaviour</title>
595
+
<programlisting role="php">
596
+
<![CDATA[
597
+
<?php
598
+
echo DateTimeImmutable::createFromFormat('Y-m-d H:i:s', '2021-17-35 16:60:97')->format(DateTimeImmutable::RFC2822);
599
+
?>
600
+
]]>
601
+
</programlisting>
602
+
&example.outputs.similar;
603
+
<screen>
604
+
<![CDATA[
605
+
Sat, 04 Jun 2022 17:01:37 +0000
606
+
]]>
607
+
</screen>
608
+
<para>
609
+
Although the result looks odd, it is correct, as the following overflows
610
+
happen:
611
+
</para>
612
+
<orderedlist>
613
+
<listitem>
614
+
<simpara>
615
+
<literal>97</literal> seconds overflows to <literal>1</literal> minute,
616
+
leaving <literal>37</literal> seconds.
617
+
</simpara>
618
+
</listitem>
619
+
<listitem>
620
+
<simpara>
621
+
<literal>61</literal> minutes overflows to <literal>1</literal> hour,
622
+
leaving <literal>1</literal> minutes.
623
+
</simpara>
624
+
</listitem>
625
+
<listitem>
626
+
<simpara>
627
+
<literal>35</literal> days overflows to <literal>1</literal> month,
628
+
leaving <literal>4</literal> days. The amount of days that are left over
629
+
depends on the month, as not every month has the same amount of days.
630
+
</simpara>
631
+
</listitem>
632
+
<listitem>
633
+
<simpara>
634
+
<literal>18</literal> months overflows to <literal>1</literal> year,
635
+
leaving <literal>6</literal> months.
636
+
</simpara>
637
+
</listitem>
638
+
</orderedlist>
639
+
</example>
640
+

641
+
<example>
642
+
<title>Overflowing day name behaviour</title>
643
+
<programlisting role="php">
644
+
<![CDATA[
645
+
<?php
646
+
$d = DateTime::createFromFormat(DateTimeInterface::RFC1123, 'Mon, 3 Aug 2020 25:00:00 +0000');
647
+
echo $d->format(DateTime::RFC1123), "\n";
648
+
?>
649
+
]]>
650
+
</programlisting>
651
+
&example.outputs.similar;
652
+
<screen>
653
+
<![CDATA[
654
+
Mon, 10 Aug 2020 01:00:00 +0000
655
+
]]>
656
+
</screen>
657
+
<para>
658
+
Although the result looks odd, it is correct, as the following overflows
659
+
happen:
660
+
</para>
661
+
<orderedlist>
662
+
<listitem>
663
+
<simpara>
664
+
<literal>3 Aug 2020 25:00:00</literal> overflows to <literal>(Tue) 4 Aug
665
+
2020 01:00</literal>.
666
+
</simpara>
667
+
</listitem>
668
+
<listitem>
669
+
<simpara>
670
+
<literal>Mon</literal> gets applied, which advances the date to
671
+
<literal>Mon, 10 Aug 2020 01:00:00</literal>. The explanation of
672
+
relative keywords such as <literal>Mon</literal> is explained in the
673
+
section on <link linkend="datetime.formats.relative">relative
674
+
formats</link>.
675
+
</simpara>
676
+
</listitem>
677
+
</orderedlist>
678
+
</example>
679
+

680
+
<para>
681
+
In order to detect overflows in dates, you can use
682
+
<methodname>DateTimeImmutable::getLastErrors</methodname>, which will
683
+
include a warning if an overflow occured.
684
+
</para>
685
+
<example>
686
+
<title>Detecting overflown dates</title>
687
+
<programlisting role="php">
688
+
<![CDATA[
689
+
<?php
690
+
$d = DateTimeImmutable::createFromFormat('Y-m-d H:i:s', '2021-17-35 16:60:97');
691
+
echo $d->format(DateTimeImmutable::RFC2822), "\n\n";
692
+

693
+
var_dump(DateTimeImmutable::GetLastErrors());
694
+
?>
695
+
]]>
696
+
</programlisting>
697
+
&example.outputs.similar;
698
+
<screen>
699
+
<![CDATA[
700
+
Sat, 04 Jun 2022 17:01:37 +0000
701
+

702
+
array(4) {
703
+
'warning_count' =>
704
+
int(2)
705
+
'warnings' =>
706
+
array(1) {
707
+
[19] =>
708
+
string(27) "The parsed date was invalid"
709
+
}
710
+
'error_count' =>
711
+
int(0)
712
+
'errors' =>
713
+
array(0) {
714
+
}
715
+
}
716
+
]]>
717
+
</screen>
718
+
</example>
719
+

720
+
<example>
721
+
<title>Greedy parsing behaviour</title>
722
+
<programlisting role="php">
723
+
<![CDATA[
724
+
<?php
725
+
print_r(date_parse_from_format('Gis', '60101'));
726
+
?>
727
+
]]>
728
+
</programlisting>
729
+
&example.outputs.similar;
730
+
<screen>
731
+
<![CDATA[
732
+
Array
733
+
(
734
+
[year] =>
735
+
[month] =>
736
+
[day] =>
737
+
[hour] => 60
738
+
[minute] => 10
739
+
[second] => 0
740
+
[fraction] => 0
741
+
[warning_count] => 1
742
+
[warnings] => Array
743
+
(
744
+
[5] => The parsed time was invalid
745
+
)
746
+

747
+
[error_count] => 1
748
+
[errors] => Array
749
+
(
750
+
[4] => A two digit second could not be found
751
+
)
752
+

753
+
[is_localtime] =>
754
+
)
755
+
]]>
756
+
</screen>
757
+
<para>
758
+
The <literal>G</literal> format is to parse 24 hour clock hours, with or
759
+
without leading zero. This requires to parse 1 or 2 digits. Because there
760
+
are two following digits, it greedily reads this as <literal>60</literal>.
761
+
</para>
762
+
<para>
763
+
The following <literal>i</literal> and <literal>s</literal> format
764
+
characters both require two digits. This means that <literal>10</literal>
765
+
is passed as minute (<literal>i</literal>), and that there are then not
766
+
enough digits left to parse for as second (<literal>s</literal>).
767
+
</para>
768
+
<para>
769
+
The <literal>errors</literal> array indicates this problem.
770
+
</para>
771
+
<para>
772
+
Additionally, an hour of <literal>60</literal> is outside the range
773
+
<literal>0</literal>-<literal>24</literal>, which causes the
774
+
<literal>warnings</literal> array to include a warning that the time is
775
+
invalid.
776
+
</para>
777
+
</example>
778
+

779
+
</refsect1>
780
+

781
+
<refsect1 role="seealso">
782
+
&reftitle.seealso;
783
+
<simplelist>
784
+
<member><function>DateTimeImmutable::__construct</function></member>
785
+
<member><function>DateTimeImmutable::getLastErrors</function></member>
786
+
<member><function>checkdate</function></member>
787
+
<member><function>strptime</function></member>
788
+
</simplelist>
789
+
</refsect1>
790
+

32
791
</refentry>
33
792
<!-- Keep this comment at the end of the file
34
793
Local variables:
35
794