<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<chapter xml:id="datetime.formats" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
 <title>Supported Date and Time Formats</title>

 <para>
  This section describes all the different formats in a BNF-like format, that the
  <classname>DateTimeImmutable</classname>, <classname>DateTime</classname>,
  <function>date_create_immutable</function>,
  <function>date_create</function>, <function>date_parse</function>, and
  <function>strtotime</function> 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 (<literal>'t'</literal> could
  be <literal>t</literal> or <literal>T</literal>), characters in
  double quotes are case-sensitive (<literal>"T"</literal> is only
  <literal>T</literal>).
 </para>
 <para>
  To format <classname>DateTimeImmutable</classname> and
  <classname>DateTime</classname> objects, please refer to the documentation
  of the <function>DateTimeInterface::format</function> method.
 </para>

 <para>
  A general set of rules should be taken into account.
 </para>
 <orderedlist>
  <listitem>
   <simpara>
    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.
   </simpara>
  </listitem>
  <listitem>
   <simpara>
    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.
   </simpara>
  </listitem>
  <listitem>
   <simpara>
    <function>strtotime</function> returns &false; if any number is outside of
    the ranges, and <function>DateTimeImmutable::__construct</function> throws
    an exception.
   </simpara>
  </listitem>
  <listitem>
   <simpara>
    If a string contains a date, all time elements are reset to 0.
   </simpara>
  </listitem>
  <listitem>
   <simpara>
    All less-significant time elements are reset to 0 if any part of a time is
    present in the given string.
   </simpara>
  </listitem>
  <listitem>
   <simpara>
    The parser is dumb, and doesn't do any checks to make it faster (and
    more generic).
   </simpara>
  </listitem>
  <listitem>
   <simpara>
    Besides rules for individual time elements, the parser also understand
    more specific <link linkend="datetime.formats.compound">compound
    formats</link>, such as parsing Unix timestamps
    (<literal>@1690388256</literal>) and ISO Weekdates
    (<literal>2008-W28-3</literal>).
   </simpara>
  </listitem>
  <listitem>
   <para>
    There is an additional check if an invalid date is provided:
    <example>
     <programlisting role="php">
<![CDATA[
<?php
$res = date_parse("2015-09-31");
var_dump($res["warnings"]);
?>
]]>
     </programlisting>
     &example.outputs;
     <screen>
<![CDATA[
array(1) {
  [11] =>
  string(27) "The parsed date was invalid"
}
]]>
     </screen>
    </example>
   </para>
  </listitem>
  <listitem>
   <para>
    It is already possible to handle the edge cases, but then
    <function>DateTimeImmutable::createFromFormat</function> must be used
    while supplying the correct format.
    <example>
     <programlisting role="php">
<![CDATA[
<?php
$res = DateTimeImmutable::createFromFormat("Y-m-d", "2015-09-34");
var_dump($res);
]]>
     </programlisting>
     &example.outputs;
     <screen>
<![CDATA[
object(DateTimeImmutable)#1 (3) {
  ["date"]=>
  string(26) "2015-10-04 17:24:43.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(13) "Europe/London"
}
]]>
     </screen>
    </example>
   </para>
  </listitem>
 </orderedlist>

 <!--Time Formats: {{{-->
 <sect1 annotations="chunk:false" xml:id="datetime.formats.time">
  <title>Time Formats</title>

  <para>
   This page describes the different date/time formats in a BNF-like syntax,
   that the <classname>DateTimeImmutable</classname>,
   <classname>DateTime</classname>, <function>date_create</function>,
   <function>date_create_immutable</function>, and
   <function>strtotime</function> parser understands.
  </para>
  <para>
   To format <classname>DateTimeImmutable</classname> and
   <classname>DateTime</classname> objects, please refer to the documentation
   of the <function>DateTimeInterface::format</function> method.
  </para>

  <table>
   <title>Used Symbols</title>
   <tgroup cols="3">
    <thead>
     <row>
      <entry>Description</entry>
      <entry>Formats</entry>
      <entry>Examples</entry>
     </row>
    </thead>
    <tbody>
     <row>
      <entry><literal>frac</literal></entry>
      <entry>. [0-9]+</entry>
      <entry>".21342", ".85"</entry>
     </row>
     <row>
      <entry><literal>hh</literal></entry>
      <entry>"0"?[1-9] | "1"[0-2]</entry>
      <entry>"04", "7", "12"</entry>
     </row>
     <row>
      <entry><literal>HH</literal></entry>
      <entry>[01][0-9] | "2"[0-4]</entry>
      <entry>"04", "07", "19"</entry>
     </row>
     <row>
      <entry><literal>meridian</literal></entry>
      <entry>[AaPp] .? [Mm] .? [\0\t ]</entry>
      <entry>"A.m.", "pM", "am."</entry>
     </row>
     <row>
      <entry><literal>MM</literal></entry>
      <entry>[0-5][0-9]</entry>
      <entry>"00", "12", "59"</entry>
     </row>
     <row>
      <entry><literal>II</literal></entry>
      <entry>[0-5][0-9]</entry>
      <entry>"00", "12", "59"</entry>
     </row>
     <row>
      <entry><literal>space</literal></entry>
      <entry>[ \t]</entry>
      <entry></entry>
     </row>
     <row>
      <entry><literal>tz</literal></entry>
      <entry>"("? [A-Za-z]{1,6} ")"? | [A-Z][a-z]+([_/][A-Z][a-z]+)+</entry>
      <entry>"CEST", "Europe/Amsterdam", "America/Indiana/Knox"</entry>
     </row>
     <row>
      <entry><literal>tzcorrection</literal></entry>
      <entry>"GMT"? [+-] <literal>hh</literal> ":"? <literal>MM</literal>?</entry>
      <entry>"+0400", "GMT-07:00", "-07:00"</entry>
     </row>
    </tbody>
   </tgroup>
  </table>

  <table>
   <title>12 Hour Notation</title>
   <tgroup cols="3">
    <thead>
     <row>
      <entry>Description</entry>
      <entry>Format</entry>
      <entry>Examples</entry>
     </row>
    </thead>
    <tbody>
     <row>
      <entry>Hour only, with meridian</entry>
      <entry><literal>hh</literal> <literal>space</literal>? <literal>meridian</literal></entry>
      <entry>"4 am", "5PM"</entry>
     </row>
     <row>
      <entry>Hour and minutes, with meridian</entry>
      <entry><literal>hh</literal> [.:] <literal>MM</literal> <literal>space</literal>? <literal>meridian</literal></entry>
      <entry>"4:08 am", "7:19P.M."</entry>
     </row>
     <row>
      <entry>Hour, minutes and seconds, with meridian</entry>
      <entry><literal>hh</literal> [.:] <literal>MM</literal> [.:] <literal>II</literal> <literal>space</literal>? <literal>meridian</literal></entry>
      <entry>"4:08:37 am", "7:19:19P.M."</entry>
     </row>
     <row>
      <entry>MS SQL (Hour, minutes, seconds and fraction with meridian)</entry>
      <entry><literal>hh</literal> ":" <literal>MM</literal> ":" <literal>II</literal> [.:] [0-9]+ <literal>meridian</literal></entry>
      <entry>"4:08:39:12313am"</entry>
     </row>
    </tbody>
   </tgroup>
  </table>

  <table>
   <title>24 Hour Notation</title>
   <tgroup cols="3">
    <thead>
     <row>
      <entry>Description</entry>
      <entry>Format</entry>
      <entry>Examples</entry>
     </row>
    </thead>
    <tbody>
     <row>
      <entry>Hour and minutes</entry>
      <entry>'t'? <literal>HH</literal> [.:] <literal>MM</literal></entry>
      <entry>"04:08", "19.19", "T23:43"</entry>
     </row>
     <row>
      <entry>Hour and minutes, no colon</entry>
      <entry>'t'? <literal>HH</literal> <literal>MM</literal></entry>
      <entry>"0408", "t1919", "T2343"</entry>
     </row>
     <row>
      <entry>Hour, minutes and seconds</entry>
      <entry>'t'? <literal>HH</literal> [.:] <literal>MM</literal> [.:] <literal>II</literal></entry>
      <entry>"04.08.37", "t19:19:19"</entry>
     </row>
     <row>
      <entry>Hour, minutes and seconds, no colon</entry>
      <entry>'t'? <literal>HH</literal> <literal>MM</literal> <literal>II</literal></entry>
      <entry>"040837", "T191919"</entry>
     </row>
     <row>
      <entry>Hour, minutes, seconds and timezone</entry>
      <entry>'t'? <literal>HH</literal> [.:] <literal>MM</literal> [.:] <literal>II</literal> <literal>space</literal>? ( <literal>tzcorrection</literal> | <literal>tz</literal> )</entry>
      <entry>"040837CEST", "T191919-0700"</entry>
     </row>
     <row>
      <entry>Hour, minutes, seconds and fraction</entry>
      <entry>'t'? <literal>HH</literal> [.:] <literal>MM</literal> [.:] <literal>II</literal> <literal>frac</literal></entry>
      <entry>"04.08.37.81412", "19:19:19.532453"</entry>
     </row>
     <row>
      <entry>Time zone information</entry>
      <entry><literal>tz</literal> | <literal>tzcorrection</literal></entry>
      <entry>"CEST", "Europe/Amsterdam", "+0430", "GMT-06:00"</entry>
     </row>
    </tbody>
   </tgroup>
  </table>
 </sect1>
 <!--}}}-->

 <!--Date Formats: {{{-->
 <sect1 annotations="chunk:false" xml:id="datetime.formats.date">
  <title>Date Formats</title>

  <para>
   This page describes the different date formats in a BNF-like syntax, that
   the <classname>DateTimeImmutable</classname>,
   <classname>DateTime</classname>, <function>date_create</function>,
   <function>date_create_immutable</function>, and
   <function>strtotime</function> parser understands.
  </para>
  <para>
   To format <classname>DateTimeImmutable</classname> and
   <classname>DateTime</classname> objects, please refer to the documentation
   of the <function>DateTimeInterface::format</function> method.
  </para>

  <table>
   <title>Used Symbols</title>
   <tgroup cols="3">
    <thead>
     <row>
      <entry>Description</entry>
      <entry>Format</entry>
      <entry>Examples</entry>
     </row>
    </thead>
    <tbody>
     <row>
      <entry><literal>daysuf</literal></entry>
      <entry>"st" | "nd" | "rd" | "th"</entry>
      <entry></entry>
     </row>
     <row>
      <entry><literal>dd</literal></entry>
      <entry>([0-2]?[0-9] | "3"[01]) <literal>daysuf</literal>?</entry>
      <entry>"7th", "22nd", "31"</entry>
     </row>
     <row>
      <entry><literal>DD</literal></entry>
      <entry>"0" [0-9] | [1-2][0-9] | "3" [01]</entry>
      <entry>"07", "31"</entry>
     </row>
     <row>
      <entry><literal>m</literal></entry>
      <entry>'january' | 'february' | 'march' | 'april' | 'may' | 'june' |
       'july' | 'august' | 'september' | 'october' | 'november' | 'december' |
       'jan' | 'feb' | 'mar' | 'apr' | 'may' | 'jun' | 'jul' | 'aug' | 'sep' |
       'sept' | 'oct' | 'nov' | 'dec' | "I" | "II" | "III" | "IV" | "V" | "VI"
       | "VII" | "VIII" | "IX" | "X" | "XI" | "XII"</entry>
      <entry></entry>
     </row>
     <row>
      <entry><literal>M</literal></entry>
      <entry>'jan' | 'feb' | 'mar' | 'apr' | 'may' | 'jun' | 'jul' | 'aug' |
       'sep' | 'sept' | 'oct' | 'nov' | 'dec'</entry>
      <entry></entry>
     </row>
     <row>
      <entry><literal>mm</literal></entry>
      <entry>"0"? [0-9] | "1"[0-2]</entry>
      <entry>"0", "04", "7", "12"</entry>
     </row>
     <row>
      <entry><literal>MM</literal></entry>
      <entry>"0" [0-9] | "1"[0-2]</entry>
      <entry>"00", "04", "07", "12"</entry>
     </row>
     <row>
      <entry><literal>y</literal></entry>
      <entry>[0-9]{1,4}</entry>
      <entry>"00", "78", "08", "8", "2008"</entry>
     </row>
     <row>
      <entry><literal>yy</literal></entry>
      <entry>[0-9]{2}</entry>
      <entry>"00", "08", "78"</entry>
     </row>
     <row>
      <entry><literal>YY</literal></entry>
      <entry>[0-9]{4}</entry>
      <entry>"2000", "2008", "1978"</entry>
     </row>
     <row>
      <entry><literal>YYY</literal></entry>
      <entry>[0-9]{5,19}</entry>
      <entry>"81412", "20192"</entry>
     </row>
    </tbody>
   </tgroup>
  </table>

  <table>
   <title>Localized Notations</title>
   <tgroup cols="3">
    <thead>
     <row>
      <entry>Description</entry>
      <entry>Format</entry>
      <entry>Examples</entry>
     </row>
    </thead>
    <tbody>
     <row>
      <entry>American month and day</entry>
      <entry><literal>mm</literal> "/" <literal>dd</literal></entry>
      <entry>"5/12", "10/27"</entry>
     </row>
     <row>
      <entry>American month, day and year</entry>
      <entry><literal>mm</literal> "/" <literal>dd</literal> "/" <literal>y</literal></entry>
      <entry>"12/22/78", "1/17/2006", "1/17/6"</entry>
     </row>
     <row>
      <entry>Four digit year, month and day with slashes</entry>
      <entry><literal>YY</literal> "/" <literal>mm</literal> "/" <literal>dd</literal></entry>
      <entry>"2008/6/30", "1978/12/22"</entry>
     </row>
     <row>
      <entry>Four digit year and month (GNU)</entry>
      <entry><literal>YY</literal> "-" <literal>mm</literal></entry>
      <entry>"2008-6", "2008-06", "1978-12"</entry>
     </row>
     <row>
      <entry>Year, month and day with dashes</entry>
      <entry><literal>y</literal> "-" <literal>mm</literal> "-" <literal>dd</literal></entry>
      <entry>"2008-6-30", "78-12-22", "8-6-21"</entry>
     </row>
     <row>
      <entry>Day, month and four digit year, with dots, tabs or dashes</entry>
      <entry><literal>dd</literal> [.\t-] <literal>mm</literal> [.-] <literal>YY</literal></entry>
      <entry>"30-6-2008", "22.12.1978"</entry>
     </row>
     <row>
      <entry>Day, month and two digit year, with dots or tabs</entry>
      <entry><literal>dd</literal> [.\t] <literal>mm</literal> "." <literal>yy</literal></entry>
      <entry>"30.6.08", "22\t12.78"</entry>
     </row>
     <row>
      <entry>Day, textual month and year</entry>
      <entry><literal>dd</literal> ([ \t.-])* <literal>m</literal> ([ \t.-])* <literal>y</literal></entry>
      <entry>"30-June 2008", "22DEC78", "14 III 1879"</entry>
     </row>
     <row>
      <entry>Textual month and four digit year (Day reset to 1)</entry>
      <entry><literal>m</literal> ([ \t.-])* <literal>YY</literal></entry>
      <entry>"June 2008", "DEC1978", "March 1879"</entry>
     </row>
     <row>
      <entry>Four digit year and textual month (Day reset to 1)</entry>
      <entry><literal>YY</literal> ([ \t.-])* <literal>m</literal></entry>
      <entry>"2008 June", "1978-XII", "1879.MArCH"</entry>
     </row>
     <row>
      <entry>Textual month, day and year</entry>
      <entry><literal>m</literal> ([ .\t-])* <literal>dd</literal> [,.stndrh\t ]+ <literal>y</literal></entry>
      <entry>"July 1st, 2008", "April 17, 1790", "May.9,78"</entry>
     </row>
     <row>
      <entry>Textual month and day</entry>
      <entry><literal>m</literal> ([ .\t-])* <literal>dd</literal> [,.stndrh\t ]*</entry>
      <entry>"July 1st,", "Apr 17", "May.9"</entry>
     </row>
     <row>
      <entry>Day and textual month</entry>
      <entry><literal>dd</literal> ([ .\t-])* <literal>m</literal></entry>
      <entry>"1 July", "17 Apr", "9.May"</entry>
     </row>
     <row>
      <entry>Month abbreviation, day and year</entry>
      <entry><literal>M</literal> "-" <literal>DD</literal> "-" <literal>y</literal></entry>
      <entry>"May-09-78", "Apr-17-1790"</entry>
     </row>
     <row>
      <entry>Year, month abbreviation and day</entry>
      <entry><literal>y</literal> "-" <literal>M</literal> "-" <literal>DD</literal></entry>
      <entry>"78-Dec-22", "1814-MAY-17"</entry>
     </row>
     <row>
      <entry>Year (and just the year)</entry>
      <entry><literal>YY</literal></entry>
      <entry>"1978", "2008"</entry>
     </row>
     <row>
      <entry>Year (expanded, 5-19 digits with sign)</entry>
      <entry>[+-] <literal>YYY</literal></entry>
      <entry>"-81120", "+20192"</entry>
     </row>
     <row>
      <entry>Textual month (and just the month)</entry>
      <entry><literal>m</literal></entry>
      <entry>"March", "jun", "DEC"</entry>
     </row>
    </tbody>
   </tgroup>
  </table>

  <table>
   <title>ISO8601 Notations</title>
   <tgroup cols="3">
    <thead>
     <row>
      <entry>Description</entry>
      <entry>Format</entry>
      <entry>Examples</entry>
     </row>
    </thead>
    <tbody>
     <row>
      <entry>Eight digit year, month and day</entry>
      <entry><literal>YY</literal> <literal>MM</literal> <literal>DD</literal></entry>
      <entry>"15810726", "19780417", "18140517"</entry>
     </row>
     <row>
      <entry>Four digit year, month and day with slashes</entry>
      <entry><literal>YY</literal> "/" <literal>MM</literal> "/" <literal>DD</literal></entry>
      <entry>"2008/06/30", "1978/12/22"</entry>
     </row>
     <row>
      <entry>Two digit year, month and day with dashes</entry>
      <entry><literal>yy</literal> "-" <literal>MM</literal> "-" <literal>DD</literal></entry>
      <entry>"08-06-30", "78-12-22"</entry>
     </row>
     <row>
      <entry>Four digit year with optional sign, month and day</entry>
      <entry>[+-]? <literal>YY</literal> "-" <literal>MM</literal> "-" <literal>DD</literal></entry>
      <entry>"-0002-07-26", "+1978-04-17", "1814-05-17"</entry>
     </row>
     <row>
      <entry>Five+ digit year with required sign, month and day</entry>
      <entry>[+-] <literal>YYY</literal> "-" <literal>MM</literal> "-" <literal>DD</literal></entry>
      <entry>"-81120-02-26", "+20192-04-17"</entry>
     </row>
    </tbody>
   </tgroup>
  </table>

  <note>
   <para>
    For the <literal>y</literal> and <literal>yy</literal>
    formats, years below 100 are handled in a special way when the
    <literal>y</literal> or <literal>yy</literal> 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".
   </para>
  </note>

  <note>
   <para>
    The "Day, month and two digit year, with dots or tabs" format
    (<literal>dd</literal> [.\t] <literal>mm</literal> "."
    <literal>yy</literal>) only works for the year values 61 (inclusive)
    to 99 (inclusive) - outside those years the <emphasis>time
    format</emphasis> "<literal>HH</literal> [.:] <literal>MM</literal>
    [.:] <literal>SS</literal>" has precedence.
   </para>
  </note>

  <note>
   <para>
    The "Year (and just the year)" format only works if a time string
    has already been found -- otherwise this format is recognised as
    <literal>HH</literal> <literal>MM</literal>.
   </para>
  </note>

  <caution>
   <para>
    It is possible to over- and underflow the <literal>dd</literal> and
    <literal>DD</literal> 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).
   </para>
   <para>
    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.
   </para>
   <para>
    It is also possible to underflow the <literal>mm</literal> and
    <literal>MM</literal> 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".
   </para>
   <para>
    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).
   </para>
  </caution>
 </sect1>
 <!--}}}-->

 <!--Compound Formats: {{{-->
 <sect1 annotations="chunk:false" xml:id="datetime.formats.compound">
  <title>Compound Formats</title>

  <para>
   This page describes the different compound date/time formats in a BNF-like
   syntax, that the <classname>DateTimeImmutable</classname>,
   <classname>DateTime</classname>, <function>date_create</function>,
   <function>date_create_immutable</function>, and
   <function>strtotime</function> parser understands.
  </para>
  <para>
   To format <classname>DateTimeImmutable</classname> and
   <classname>DateTime</classname> objects, please refer to the documentation
   of the <function>DateTimeInterface::format</function> method.
  </para>

  <table>
   <title>Used Symbols</title>
   <tgroup cols="3">
    <thead>
     <row>
      <entry>Description</entry>
      <entry>Formats</entry>
      <entry>Examples</entry>
     </row>
    </thead>
    <tbody>
     <row>
      <entry><literal>DD</literal></entry>
      <entry>"0" [0-9] | [1-2][0-9] | "3" [01]</entry>
      <entry>"02", "12", "31"</entry>
     </row>
     <row>
      <entry><literal>doy</literal></entry>
      <entry>"00"[1-9] | "0"[1-9][0-9] | [1-2][0-9][0-9] | "3"[0-5][0-9] | "36"[0-6]</entry>
      <entry>"001", "012", "180", "350", "366"</entry>
     </row>
     <row>
      <entry><literal>frac</literal></entry>
      <entry>. [0-9]+</entry>
      <entry>".21342", ".85"</entry>
     </row>
     <row>
      <entry><literal>hh</literal></entry>
      <entry>"0"?[1-9] | "1"[0-2]</entry>
      <entry>"04", "7", "12"</entry>
     </row>
     <row>
      <entry><literal>HH</literal></entry>
      <entry>[01][0-9] | "2"[0-4]</entry>
      <entry>"04", "07", "19"</entry>
     </row>
     <row>
      <entry><literal>meridian</literal></entry>
      <entry>[AaPp] .? [Mm] .? [\0\t ]</entry>
      <entry>"A.m.", "pM", "am."</entry>
     </row>
     <row>
      <entry><literal>ii</literal></entry>
      <entry>[0-5]?[0-9]</entry>
      <entry>"04", "8", "59"</entry>
     </row>
     <row>
      <entry><literal>II</literal></entry>
      <entry>[0-5][0-9]</entry>
      <entry>"04", "08", "59"</entry>
     </row>
     <row>
      <entry><literal>M</literal></entry>
      <entry>'jan' | 'feb' | 'mar' | 'apr' | 'may' | 'jun' | 'jul' | 'aug' | 'sep' | 'sept' | 'oct' | 'nov' | 'dec'</entry>
      <entry></entry>
     </row>
     <row>
      <entry><literal>MM</literal></entry>
      <entry>[0-1][0-9]</entry>
      <entry>"00", "12"</entry>
     </row>
     <row>
      <entry><literal>space</literal></entry>
      <entry>[ \t]</entry>
      <entry></entry>
     </row>
     <row>
      <entry><literal>ss</literal></entry>
      <entry>([0-5]?[0-9])|60</entry>
      <entry>"04", "8", "59", "60" (leap second)</entry>
     </row>
     <row>
      <entry><literal>SS</literal></entry>
      <entry>[0-5][0-9]</entry>
      <entry>"04", "08", "59"</entry>
     </row>
     <row>
      <entry><literal>W</literal></entry>
      <entry>"0"[1-9] | [1-4][0-9] | "5"[0-3]</entry>
      <entry>"05", "17", "53"</entry>
     </row>
     <row>
      <entry><literal>tzcorrection</literal></entry>
      <entry>"GMT"? [+-] <literal>hh</literal> ":"? <literal>II</literal>?</entry>
      <entry>"+0400", "GMT-07:00", "-07:00"</entry>
     </row>
     <row>
      <entry><literal>YY</literal></entry>
      <entry>[0-9]{4}</entry>
      <entry>"2000", "2008", "1978"</entry>
     </row>
    </tbody>
   </tgroup>
  </table>

  <table>
   <title>Standards Formats</title>
   <tgroup cols="2">
    <thead>
     <row>
      <entry>Description</entry>
      <entry>Examples</entry>
     </row>
    </thead>
    <tbody>
     <row>
      <entry>ATOM</entry>
      <entry>"2022-06-02T16:58:35+00:00"</entry>
     </row>
     <row>
      <entry>COOKIE</entry>
      <entry>"Thursday, 02-Jun-2022 16:58:35 UTC"</entry>
     </row>
     <row>
      <entry>ISO8601</entry>
      <entry>"2022-06-02T16:58:35+0000"</entry>
     </row>
     <row>
      <entry><link xlink:href="&url.rfc;822">RFC 822</link></entry>
      <entry>"Thu, 02 Jun 22 16:58:35 +0000"</entry>
     </row>
     <row>
      <entry><link xlink:href="&url.rfc;850">RFC 850</link></entry>
      <entry>"Thursday, 02-Jun-22 16:58:35 UTC"</entry>
     </row>
     <row>
      <entry><link xlink:href="&url.rfc;1036">RFC 1036</link></entry>
      <entry>"Thu, 02 Jun 22 16:58:35 +0000"</entry>
     </row>
     <row>
      <entry><link xlink:href="&url.rfc;1123">RFC 1123</link></entry>
      <entry>"Thu, 02 Jun 2022 16:58:35 +0000"</entry>
     </row>
     <row>
      <entry><link xlink:href="&url.rfc;2822">RFC 2822</link></entry>
      <entry>"Thu, 02 Jun 2022 16:58:35 +0000"</entry>
     </row>
     <row>
      <entry><link xlink:href="&url.rfc;3339">RFC 3339</link></entry>
      <entry>"2022-06-02T16:58:35+00:00"</entry>
     </row>
     <row>
      <entry><link xlink:href="&url.rfc;3339">RFC 3339</link> Extended</entry>
      <entry>"2022-06-02T16:58:35.698+00:00"</entry>
     </row>
     <row>
      <entry><link xlink:href="&url.rfc;7231">RFC 7231</link></entry>
      <entry>"Thu, 02 Jun 2022 16:58:35 GMT"</entry>
     </row>
     <row>
      <entry>RSS</entry>
      <entry>"Thu, 02 Jun 2022 16:58:35 +0000"</entry>
     </row>
     <row>
      <entry>W3C</entry>
      <entry>"2022-06-02T16:58:35+00:00"</entry>
     </row>
    </tbody>
   </tgroup>
  </table>

  <table>
   <title>Localized Notations</title>
   <tgroup cols="3">
    <thead>
     <row>
      <entry>Description</entry>
      <entry>Format</entry>
      <entry>Examples</entry>
     </row>
    </thead>
    <tbody>
     <row>
      <entry>Common Log Format</entry>
      <entry><literal>dd</literal> "/" <literal>M</literal> "/" <literal>YY</literal> : <literal>HH</literal> ":" <literal>II</literal> ":" <literal>SS</literal> <literal>space</literal> <literal>tzcorrection</literal></entry>
      <entry>"10/Oct/2000:13:55:36 -0700"</entry>
     </row>
     <row>
      <entry>EXIF</entry>
      <entry><literal>YY</literal> ":" <literal>MM</literal> ":" <literal>DD</literal> " " <literal>HH</literal> ":" <literal>II</literal> ":" <literal>SS</literal></entry>
      <entry>"2008:08:07 18:11:31"</entry>
     </row>
     <row>
      <entry>ISO year with ISO week</entry>
      <entry><literal>YY</literal> "-"? "W" <literal>W</literal></entry>
      <entry>"2008W27", "2008-W28"</entry>
     </row>
     <row>
      <entry>ISO year with ISO week and day</entry>
      <entry><literal>YY</literal> "-"? "W" <literal>W</literal> "-"? [0-7]</entry>
      <entry>"2008W273", "2008-W28-3"</entry>
     </row>
     <row>
      <entry>MySQL</entry>
      <entry><literal>YY</literal> "-" <literal>MM</literal> "-" <literal>DD</literal> " " <literal>HH</literal> ":" <literal>II</literal> ":" <literal>SS</literal></entry>
      <entry>"2008-08-07 18:11:31"</entry>
     </row>
     <row>
      <entry>PostgreSQL: Year with day-of-year</entry>
      <entry><literal>YY</literal> "."? <literal>doy</literal></entry>
      <entry>"2008.197", "2008197"</entry>
     </row>
     <row>
      <entry>SOAP</entry>
      <entry><literal>YY</literal> "-" <literal>MM</literal> "-" <literal>DD</literal> "T" <literal>HH</literal> ":" <literal>II</literal> ":" <literal>SS</literal> <literal>frac</literal> <literal>tzcorrection</literal>?</entry>
      <entry>"2008-07-01T22:35:17.02", "2008-07-01T22:35:17.03+08:00"</entry>
     </row>
     <row>
      <entry>Unix Timestamp</entry>
      <entry>"@" "-"? [0-9]+</entry>
      <entry>"@1215282385"</entry>
     </row>
     <row>
      <entry>Unix Timestamp with microseconds</entry>
      <entry>"@" "-"? [0-9]+ "." [0-9]{0,6}</entry>
      <entry>"@1607974647.503686"</entry>
     </row>
     <row>
      <entry>XMLRPC</entry>
      <entry><literal>YY</literal> <literal>MM</literal> <literal>DD</literal> "T" <literal>hh</literal> ":" <literal>II</literal> ":" <literal>SS</literal></entry>
      <entry>"20080701T22:38:07", "20080701T9:38:07"</entry>
     </row>
     <row>
      <entry>XMLRPC (Compact)</entry>
      <entry><literal>YY</literal> <literal>MM</literal> <literal>DD</literal> 't' <literal>hh</literal> <literal>II</literal> <literal>SS</literal></entry>
      <entry>"20080701t223807", "20080701T093807"</entry>
     </row>
     <row>
      <entry>WDDX</entry>
      <entry><literal>YY</literal> "-" <literal>mm</literal> "-" <literal>dd</literal> "T" <literal>hh</literal> ":" <literal>ii</literal> ":" <literal>ss</literal></entry>
      <entry>"2008-7-1T9:3:37"</entry>
     </row>
    </tbody>
   </tgroup>
  </table>

  <note>
   <para>
    The "W" in the "ISO year with ISO week" and "ISO year with ISO week
    and day" formats is case-sensitive, you can only use the upper case
    "W".
   </para>
   <para>
    The "T" in the SOAP, XMLRPC and WDDX formats is case-sensitive, you
    can only use the upper case "T".
   </para>
   <para>
    The "Unix Timestamp" format sets the timezone to UTC.
   </para>
  </note>
 </sect1>
 <!--}}}-->

 <!--Relative Formats: {{{-->
 <sect1 annotations="chunk:false" xml:id="datetime.formats.relative">
  <title>Relative Formats</title>
  <para>
   This page describes the different relative date/time formats in a BNF-like
   syntax, that the <classname>DateTimeImmutable</classname>,
   <classname>DateTime</classname>, <function>date_create</function>,
   <function>date_create_immutable</function>, and
   <function>strtotime</function> parser understands.
  </para>
  <para>
   To format <classname>DateTimeImmutable</classname> and
   <classname>DateTime</classname> objects, please refer to the documentation
   of the <function>DateTimeInterface::format</function> method.
  </para>

  <table>
   <title>Used Symbols</title>
   <tgroup cols="2">
    <thead>
     <row>
      <entry>Description</entry>
      <entry>Format</entry>
     </row>
    </thead>
    <tbody>
     <row>
      <entry><literal>dayname</literal></entry>
      <entry>'sunday' | 'monday' | 'tuesday' | 'wednesday' | 'thursday' |
       'friday' | 'saturday' | 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' |
       'sat'</entry>
     </row>
     <row>
      <entry><literal>daytext</literal></entry>
      <entry>'weekday' | 'weekdays'</entry>
     </row>
     <row>
      <entry><literal>number</literal></entry>
      <entry>[+-]?[0-9]+</entry>
     </row>
     <row>
      <entry><literal>ordinal</literal></entry>
      <entry>'first' | 'second' | 'third' | 'fourth' | 'fifth' | 'sixth' |
       'seventh' | 'eighth' | 'ninth' | 'tenth' | 'eleventh' | 'twelfth' |
       'next' | 'last' | 'previous' | 'this'</entry>
     </row>
     <row>
      <entry><literal>reltext</literal></entry>
      <entry>'next' | 'last' | 'previous' | 'this'</entry>
     </row>
     <row>
      <entry><literal>space</literal></entry>
      <entry>[ \t]+</entry>
     </row>
     <row>
      <entry><literal>unit</literal></entry>
      <entry>'ms' | 'µs' | (( 'msec' | 'millisecond' | 'µsec' | 'microsecond'
      | 'usec' | 'sec' | 'second' | 'min' | 'minute' | 'hour' | 'day' |
      'fortnight' | 'forthnight' | 'month' | 'year') 's'?) | 'weeks' |
      <literal>daytext</literal></entry>
     </row>
    </tbody>
   </tgroup>
  </table>

  <table>
   <title>Day-based Notations</title>
   <tgroup cols="3">
    <thead>
     <row>
      <entry>Format</entry>
      <entry>Description</entry>
      <entry>Examples</entry>
     </row>
    </thead>
    <tbody>
     <row>
      <entry>'yesterday'</entry>
      <entry>Midnight of yesterday</entry>
      <entry>"yesterday 14:00"</entry>
     </row>
     <row>
      <entry>'midnight'</entry>
      <entry>The time is set to 00:00:00</entry>
      <entry></entry>
     </row>
     <row>
      <entry>'today'</entry>
      <entry>The time is set to 00:00:00</entry>
      <entry></entry>
     </row>
     <row>
      <entry>'now'</entry>
      <entry>Now - this is simply ignored</entry>
      <entry></entry>
     </row>
     <row>
      <entry>'noon'</entry>
      <entry>The time is set to 12:00:00</entry>
      <entry>"yesterday noon"</entry>
     </row>
     <row>
      <entry>'tomorrow'</entry>
      <entry>Midnight of tomorrow</entry>
      <entry></entry>
     </row>
     <row>
      <entry>'back of' <literal>hour</literal></entry>
      <entry>15 minutes past the specified hour</entry>
      <entry>"back of 7pm", "back of 15"</entry>
     </row>
     <row>
      <entry>'front of' <literal>hour</literal></entry>
      <entry>15 minutes before the specified hour</entry>
      <entry>"front of 5am", "front of 23"</entry>
     </row>
     <row>
      <entry>'first day of'</entry>
      <entry>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</entry>
      <entry>"first day of January 2008"</entry>
     </row>
     <row>
      <entry>'last day of'</entry>
      <entry>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</entry>
      <entry>"last day of next month"</entry>
     </row>
     <row>
      <entry><literal>ordinal</literal> <literal>space</literal> <literal>dayname</literal> <literal>space</literal> 'of'</entry>
      <entry>Calculates the <literal>x</literal>-th week day of the current month.</entry>
      <entry>"first sat of July 2008"</entry>
     </row>
     <row>
      <entry>'last' <literal>space</literal> <literal>dayname</literal> <literal>space</literal> 'of'</entry>
      <entry>Calculates the <emphasis>last</emphasis> week day of the current month.</entry>
      <entry>"last sat of July 2008"</entry>
     </row>
     <row>
      <entry><literal>number</literal> <literal>space</literal>? (<literal>unit</literal> | 'week')</entry>
      <entry>Handles relative time items where the value is a number.</entry>
      <entry>"+5 weeks", "12 day", "-7 weekdays"</entry>
     </row>
     <row>
      <entry>(<literal>ordinal</literal> | <literal>reltext</literal>) <literal>space</literal> <literal>unit</literal></entry>
      <entry>Handles relative time items where the value is text.
      <literal>last</literal> and <literal>previous</literal> are equivalent
      to <literal>-1</literal>, <literal>this</literal> to nothing, and
      <literal>next</literal> to <literal>+1</literal>.</entry>
      <entry>"fifth day", "second month", "last day", "previous year"</entry>
     </row>
     <row>
      <entry>'ago'</entry>
      <entry>Negates all the values of previously found relative time items.</entry>
      <entry>"2 days ago", "8 days ago 14:00", "2 months 5 days ago", "2 months ago 5 days", "2 days ago"</entry>
     </row>
     <row>
      <entry><literal>dayname</literal></entry>
      <entry>
       Moves to the next day of this name. (See <link
       linkend="datetime.formats.relative.dayname-note">note</link>)
      </entry>
      <entry>"Monday"</entry>
     </row>
     <row>
      <entry><literal>reltext</literal> <literal>space</literal> 'week'</entry>
      <entry>Handles the special format "weekday + last/this/next week".</entry>
      <entry>"Monday next week"</entry>
     </row>
    </tbody>
   </tgroup>
  </table>

  <note>
   <para>
    Relative statements are always processed <emphasis>after</emphasis>
    non-relative statements. This makes "+1 week july 2008" and "july
    2008 +1 week" equivalent.
   </para>
   <para>
    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.
   </para>
   <para>
    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
    <function>DateTime::modify</function> or
    <function>DateTimeImmutable::modify</function>, the referent is the object
    on which the <literal>modify()</literal> method is called.
   </para>
  </note>

  <note>
   <para xml:id="datetime.formats.relative.dayname-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.
   </para>
   <orderedlist>
    <listitem>
     <simpara>
      "<literal>dayname</literal>" does <emphasis>not</emphasis> advance to
      another day. (Example: "Wed July 23rd, 2008" means "2008-07-23").
     </simpara>
    </listitem>
    <listitem>
     <simpara>
      "<literal>number</literal> <literal>dayname</literal>" does
      <emphasis>not</emphasis> advance to another day. (Example: "1
      wednesday july 23rd, 2008" means "2008-07-23").
     </simpara>
    </listitem>
    <listitem>
     <simpara>
      "<literal>number</literal> week <literal>dayname</literal>" will
      first add the number of weeks, but does <emphasis>not</emphasis>
      advance to another day. In this case "<literal>number</literal>
      week" and "<literal>dayname</literal>" are two distinct blocks.
      (Example: "+1 week wednesday july 23rd, 2008" means "2008-07-30").
     </simpara>
    </listitem>
    <listitem>
     <simpara>
      "<literal>ordinal</literal> <literal>dayname</literal>"
      <emphasis>does</emphasis> advance to another day. (Example "first
      wednesday july 23rd, 2008" means "2008-07-30").
     </simpara>
    </listitem>
    <listitem>
     <simpara>
      "<literal>number</literal> week <literal>ordinal</literal>
      <literal>dayname</literal>" will first add the number of
      weeks, and then <emphasis>advances</emphasis> to another
      day. In this case "<literal>number</literal> week" and
      "<literal>ordinal</literal> <literal>dayname</literal>" are two
      distinct blocks. (Example: "+1 week first wednesday july 23rd,
      2008" means "2008-08-06").
     </simpara>
    </listitem>
    <listitem>
     <simpara>
      "<literal>ordinal</literal> <literal>dayname</literal> 'of' "
      does <emphasis>not</emphasis> 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).
     </simpara>
    </listitem>
   </orderedlist>
   <para>
    Also observe that the "of" in "<literal>ordinal</literal>
    <literal>space</literal> <literal>dayname</literal>
    <literal>space</literal> 'of' " and "'last' <literal>space</literal>
    <literal>dayname</literal> <literal>space</literal> 'of' " does
    something special.
   </para>
   <orderedlist>
    <listitem>
     <simpara>
      It sets the day-of-month to 1.
     </simpara>
    </listitem>
    <listitem>
     <simpara>
      "<literal>ordinal</literal> <literal>dayname</literal> 'of' " does
      <emphasis>not</emphasis> advance to another day. (Example: "first
      tuesday of july 2008" means "2008-07-01").
     </simpara>
    </listitem>
    <listitem>
     <simpara>
      "<literal>ordinal</literal> <literal>dayname</literal> "
      <emphasis>does</emphasis> advance to another day. (Example: "first
      tuesday july 2008" means "2008-07-08", see also point 4 in the
      list above).
     </simpara>
    </listitem>
    <listitem>
     <simpara>
      "'last' <literal>dayname</literal> 'of' " takes the last
      <literal>dayname</literal> of the current month. (Example: "last
      wed of july 2008" means "2008-07-30")
     </simpara>
    </listitem>
    <listitem>
     <simpara>
      "'last' <literal>dayname</literal>" takes the last
      <literal>dayname</literal> 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").
     </simpara>
    </listitem>
   </orderedlist>
  </note>
  <note>
   <para>
    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.
   </para>
  </note>
  <note>
   <para>
    <literal>number</literal> is an <emphasis>integer</emphasis> number; if a
    decimal number is given, the dot (or comma) is likely interpreted as delimiter.
    For instance, <literal>'+1.5 hours'</literal> is parsed like
    <literal>'+1 5 hours'</literal>, not as <literal>'+1 hour +30 minutes'</literal>.
   </para>
  </note>

  <sect2 role="changelog">
   &reftitle.changelog;
   <para>
    <informaltable>
     <tgroup cols="2">
      <thead>
       <row>
        <entry>&Version;</entry>
        <entry>&Description;</entry>
       </row>
      </thead>
      <tbody>
       <row>
        <entry>8.2.0</entry>
        <entry>
         <literal>number</literal> no longer accepts multiple signs,
         e.g. <literal>+-2</literal>.
        </entry>
       </row>
      <row>
        <entry>7.0.8</entry>
        <entry>
         Weeks always start on monday. Formerly, sunday would also be considered
         to start a week.
        </entry>
       </row>
      </tbody>
     </tgroup>
    </informaltable>
   </para>
  </sect2>
 </sect1>
 <!--}}}-->

</chapter>

<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=marker fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->

