Допустимые форматы даты и времени

Раздел описывает разные форматы в BNF-подобном синтаксисе, которые принимает парсер: DateTimeImmutable, DateTime, date_create_immutable(), date_create(), date_parse() и strtotime(). Форматы сгруппированы по разделам. В большей части случаев форматы из разных разделов, разделённые пробелом, запятой или точкой, разрешается указывать в одной и той же строке даты и времени. Для каждого поддерживаемого формата приводится один или ряд примеров, и описание формата. Символы в одинарных кавычках нечувствительны к регистру ('t' эквивалентно как t, так и T), символы в двойных кавычках чувствительны к регистру ("T" означает только T).

О форматировании объектов DateTimeImmutable и DateTime рассказывает документация метода DateTimeInterface::format().

При форматировании дат рекомендуют учитывать общие правила.

  1. Парсер разрешает для каждой единицы измерения (год, месяц, день, час, минута, секунда) полный диапазон значений. Для года — 4 цифры, для месяца — 0-12, дня — 0-31, для часа — 0-24, а для минуты — 0-59.
  2. Для секунд допускается значение 60, поскольку иногда появляются строки даты с високосной секундой. Но PHP реализует Unix-время, в котором значение "60" недопустимо для числа секунд, и поэтому возникает переполнение.
  3. Функция strtotime() возвращает значение false, если какое-либо число выходит за пределы диапазонов, а конструктор DateTimeImmutable::__construct() выбрасывает исключение.
  4. Каждый элемент времени сбрасывается на 0, если строка содержит дату.
  5. Каждый менее значимый элемент времени сбрасывается до 0, если строка содержит какую-либо часть времени.
  6. Парсер только разбирает строку и не выполняет проверок, чтобы работать быстро и универсально.
  7. Кроме правил для отдельных элементов времени синтаксический анализатор понимает и более специфические комбинированные форматы наподбие разбора меток Unix-времени — @1690388256 и дат недели в формате ISO — 2008-W28-3.
  8. Неверные даты проверяются отдельно:

    <?php

    $res
    = date_parse("2015-09-31");
    var_dump($res["warnings"]);

    ?>

    Результат выполнения приведённого примера:

    array(1) {
      [11] =>
      string(27) "The parsed date was invalid"
    }
    

  9. Крайние случаи уже обрабатывают, для этого вызывают метод DateTimeImmutable::createFromFormat() и указывают правильный формат.

    <?php

    $res
    = DateTimeImmutable::createFromFormat("Y-m-d", "2015-09-34");
    var_dump($res);

    ?>

    Результат выполнения приведённого примера:

    object(DateTimeImmutable)#1 (3) {
      ["date"]=>
      string(26) "2015-10-04 17:24:43.000000"
      ["timezone_type"]=>
      int(3)
      ["timezone"]=>
      string(13) "Europe/London"
    }
    

Форматы времени

Страница описывает форматы даты и времени в BNF-подобном синтаксисе, которые понимает парсер методов DateTimeImmutable и DateTime, и функций date_create(), date_create_immutable() и strtotime().

О форматировании объектов DateTimeImmutable и DateTime рассказывает документация метода DateTimeInterface::format().

Символы форматирования времени
Описание Формат Примеры
frac (дробная часть) . [0-9]+ ".21342", ".85"
hh (часы в 12-часовом формате) "0"?[1-9] | "1"[0-2] "04", "7", "12"
HH (часы в 24-часовом формате) [01][0-9] | "2"[0-4] "04", "07", "19"
meridian (Ante meridiem или Post meridiem) [AaPp] .? [Mm] .? [\0\t ] "A.m.", "pM", "am."
MM (минуты) [0-5][0-9] "00", "12", "59"
II (секунды) [0-5][0-9] "00", "12", "59"
space (символ пробела или табуляции) [ \t]  
tz (часовой пояс) "("? [A-Za-z]{1,6} ")"? | [A-Z][a-z]+([_/][A-Z][a-z]+)+ "CEST", "Europe/Amsterdam", "America/Indiana/Knox"
tzcorrection (числовое значение смещения часового пояса) "GMT"? [+-] hh ":"? MM? "+0400", "GMT-07:00", "-07:00"
12-часовой формат
Описание Формат Примеры
Только часы (с Ante meridiem или Post meridiem) hh space? meridian "4 am", "5PM"
Часы и минуты (с Ante meridiem или Post meridiem) hh [.:] MM space? meridian "4:08 am", "7:19P.M."
Часы, минуты и секунды (с Ante meridiem или Post meridiem) hh [.:] MM [.:] II space? meridian "4:08:37 am", "7:19:19P.M."
MS SQL (Часы, минуты, секунды и дробная часть с Ante meridiem или Post meridiem) hh ":" MM ":" II [.:] [0-9]+ meridian "4:08:39:12313am"
24-часовой формат
Описание Формат Примеры
Часы и минуты 't'? HH [.:] MM "04:08", "19.19", "T23:43"
Часы и минуты (без двоеточия-разделителя) 't'? HH MM "0408", "t1919", "T2343"
Часы, минуты и секунды 't'? HH [.:] MM [.:] II "04.08.37", "t19:19:19"
Часы, минуты и секунды (без двоеточия-разделителя) 't'? HH MM II "040837", "T191919"
Часы, минуты, секунды и часовой пояс 't'? HH [.:] MM [.:] II space? ( tzcorrection | tz ) "040837CEST", "T191919-0700"
Часы, минуты, секунды и дробная часть 't'? HH [.:] MM [.:] II frac "04.08.37.81412", "19:19:19.532453"
Сведения о часовом поясе tz | tzcorrection "CEST", "Europe/Amsterdam", "+0430", "GMT-06:00"

Форматы даты

Эта страница описывает форматы даты в BNF-подобном синтаксисе, которые понимает парсер функций: DateTimeImmutable, DateTime, date_create(), date_create_immutable() и strtotime().

Чтобы отформатировать объекты DateTimeImmutable и DateTime, обратитесь к документации метода DateTimeInterface::format().

Символы форматирования даты
Описание Формат Примеры
daysuf (суффикс порядкового числительного дня месяца) "st" | "nd" | "rd" | "th"  
dd (день месяца без ведущих нулей) ([0-2]?[0-9] | "3"[01]) daysuf? "7th", "22nd", "31"
DD (день месяца, 2 цифры с ведущим нулём) "0" [0-9] | [1-2][0-9] | "3" [01] "07", "31"
m (полное или сокращённое название месяца) '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"  
M (сокращённое название месяца) 'jan' | 'feb' | 'mar' | 'apr' | 'may' | 'jun' | 'jul' | 'aug' | 'sep' | 'sept' | 'oct' | 'nov' | 'dec'  
mm (порядковый номер месяца) "0"? [0-9] | "1"[0-2] "0", "04", "7", "12"
MM (порядковый номер месяца, 2 цифры с ведущим нулём) "0" [0-9] | "1"[0-2] "00", "04", "07", "12"
y (порядковый номер года) [0-9]{1,4} "00", "78", "08", "8", "2008"
yy (порядковый номер года, 2 цифры) [0-9]{2} "00", "08", "78"
YY (порядковый номер года, 4 цифры) [0-9]{4} "2000", "2008", "1978"
YYY [0-9]{5,19} "81412", "20192"
Региональные нотации
Описание Формат Примеры
Месяц и день в американской нотации mm "/" dd "5/12", "10/27"
Месяц, день и год в американской нотации mm "/" dd "/" y "12/22/78", "1/17/2006", "1/17/6"
4 цифры года, месяц и день со слешем-разделителем YY "/" mm "/" dd "2008/6/30", "1978/12/22"
4 цифры года и месяц (GNU) YY "-" mm "2008-6", "2008-06", "1978-12"
Год, месяц и день с дефисом-разделителем y "-" mm "-" dd "2008-6-30", "78-12-22", "8-6-21"
День, месяц и 4 цифры года с разделителем в виде точки, символа табуляции или дефиса dd [.\t-] mm [.-] YY "30-6-2008", "22.12.1978"
День, месяц и 2 цифры года с разделителем в виде точки или символа табуляции dd [.\t] mm "." yy "30.6.08", "22.12.78"
День, название месяца и год dd ([ \t.-])* m ([ \t.-])* y "30-June 2008", "22DEC78", "14 III 1879"
Название месяца и 4 цифры года (день месяца сбрасывается на 1) m ([ \t.-])* YY "June 2008", "DEC1978", "March 1879"
4 цифры года и название месяца (день месяца сбрасывается на 1) YY ([ \t.-])* m "2008 June", "1978-XII", "1879.MArCH"
Название месяца, день и год m ([ .\t-])* dd [,.stndrh\t ]+ y "July 1st, 2008", "April 17, 1790", "May.9,78"
Название месяца и день m ([ .\t-])* dd [,.stndrh\t ]* "July 1st,", "Apr 17", "May.9"
День и название месяца dd ([ .\t-])* m "1 July", "17 Apr", "9.May"
Сокращённое название месяца, день и год M "-" DD "-" y "May-09-78", "Apr-17-1790"
Год, сокращённое название месяца и день y "-" M "-" DD "78-Dec-22", "1814-MAY-17"
Только год YY "1978", "2008"
Год (расширенный, 5-19 цифр со знаком) [+-] YYY "-81120", "+20192"
Только название месяца m "March", "jun", "DEC"
Нотации стандарта ISO8601
Описание Формат Примеры
8 цифр (год, месяц и день) YY MM DD "15810726", "19780417", "18140517"
8 цифр (год, месяц и день) со слешем-разделителем YY "/" MM "/" DD "2008/06/30", "1978/12/22"
2 цифры года, месяц и день с дефисом-разделителем yy "-" MM "-" DD "08-06-30", "78-12-22"
4 цифры года с необязательным знаком, месяц и день [+-]? YY "-" MM "-" DD "-0002-07-26", "+1978-04-17", "1814-05-17"
Пятизначный год с обязательным знаком, месяцем и днём [+-] YYY "-" MM "-" DD "-81120-02-26", "+20192-04-17"

Замечание:

Форматы y и yy для годов меньше 100 обрабатываются в исключительных случаях при использовании символов y или yy. К году добавляется значение 2000, если год попадает в диапазон 0-69 (включительно). К году добавляется значение 1900, если год принадлежит диапазону 70-99 (включительно). Поэтому дата "00-01-01" интерпретируется как "2000-01-01".

Замечание:

Формат "День, месяц и 2 цифры года с разделителем в виде точки или символа табуляции" (dd [.\t] mm "." yy) работает только для годов из диапазона 61-99 (включительно). За пределами этого диапазона отдаётся предпочтение формату времени "HH [.:] MM [.:] SS".

Замечание:

Формат «Год (и только год)» надёжно работает, только если метод уже нашёл строку времени, иначе, если четыре цифры года соответствуют формату HH MM, вместо года устанавливаются эти два элемента даты.

Для согласованного разбора только года вызывают метод DateTimeImmutable::createFromFormat() со спецификатором Y.

Предостережение

Возможен выход за границы диапазона форматов dd и DD. День месяца с порядковым номером 0 подразумевает последний день предыдущего месяца в результате выхода за границы диапазона. Согласно написанному, "2008-08-00" равносильно "2008-07-31", а "2008-06-31" соответствует "2008-07-01" (в июне всего 30 дней).

Обратите внимание на ограничение диапазона дней: 0-31, как указывает регулярное выражение в предыдущих параграфах. Поэтому дата наподобие "2008-06-32" некорректна.

Допускается также выход за границы диапазона для форматов mm и MM со значением 0. Значение месяца 0 соответствует декабрю предыдущего года. Например, дата "2008-00-22" равносильна "2007-12-22".

Если учесть два предыдущих замечания и выход за границы диапазона дней и месяцев, получим следующее: дата "2008-00-00" в первую очередь преобразуется в "2007-12-00", которая будет преобразована в "2007-11-30". То же случится с датой "0000-00-00", которая преобразуется к "-0001-11-30" (минус первый год в календаре ISO 8601 и 2 год до н. э. по григорианскому календарю).

Составные форматы

Страница описывает разные составные форматы даты и времени в BNF-подобном синтаксисе, которые понимает парсер методов DateTimeImmutable и DateTime, и функций date_create(), date_create_immutable() и strtotime().

О форматировании объектов DateTimeImmutable и DateTime рассказывает документация метода DateTimeInterface::format().

Символы составного форматирования
Описание Форматы Примеры
DD (день месяца с ведущим нулём) "0" [0-9] | [1-2][0-9] | "3" [01] "02", "12", "31"
doy (день в году) "00"[1-9] | "0"[1-9][0-9] | [1-2][0-9][0-9] | "3"[0-5][0-9] | "36"[0-6] "001", "012", "180", "350", "366"
frac (дробная часть) . [0-9]+ ".21342", ".85"
hh (часы) "0"?[1-9] | "1"[0-2] "04", "7", "12"
HH (часы с ведущим нулём) [01][0-9] | "2"[0-4] "04", "07", "19"
meridian (Ante meridiem или Post meridiem) [AaPp] .? [Mm] .? [\0\t ] "A.m.", "pM", "am."
ii (минуты) [0-5]?[0-9] "04", "8", "59"
II (минуты с ведущим нулём) [0-5][0-9] "04", "08", "59"
M (сокращённое наименование месяца) 'jan' | 'feb' | 'mar' | 'apr' | 'may' | 'jun' | 'jul' | 'aug' | 'sep' | 'sept' | 'oct' | 'nov' | 'dec'  
MM (месяц с ведущим нулём) [0-1][0-9] "00", "12"
space (символ пробела или табуляции) [ \t]  
ss (секунды) ([0-5]?[0-9])|60 "04", "8", "59", "60" (дополнительная секунда)
SS (секунды с ведущим нулём) [0-5][0-9] "04", "08", "59"
W (неделя в году) "0"[1-9] | [1-4][0-9] | "5"[0-3] "05", "17", "53"
tzcorrection (смещение часового пояса) "GMT"? [+-] hh ":"? II? "+0400", "GMT-07:00", "-07:00"
YY (4 цифры года) [0-9]{4} "2000", "2008", "1978"
Форматы стандартов
Описание Примеры
ATOM "2022-06-02T16:58:35+00:00"
COOKIE "Thursday, 02-Jun-2022 16:58:35 UTC"
ISO8601 "2022-06-02T16:58:35+0000"
» RFC 822 "Thu, 02 Jun 22 16:58:35 +0000"
» RFC 850 "Thursday, 02-Jun-22 16:58:35 UTC"
» RFC 1036 "Thu, 02 Jun 22 16:58:35 +0000"
» RFC 1123 "Thu, 02 Jun 2022 16:58:35 +0000"
» RFC 2822 "Thu, 02 Jun 2022 16:58:35 +0000"
» RFC 3339 "2022-06-02T16:58:35+00:00"
» RFC 3339 Extended "2022-06-02T16:58:35.698+00:00"
» RFC 7231 "Thu, 02 Jun 2022 16:58:35 GMT"
RSS "Thu, 02 Jun 2022 16:58:35 +0000"
W3C "2022-06-02T16:58:35+00:00"
Региональные нотации
Описание Формат Примеры
Общий формат log-записей dd "/" M "/" YY : HH ":" II ":" SS space tzcorrection "10/Oct/2000:13:55:36 -0700"
EXIF YY ":" MM ":" DD " " HH ":" II ":" SS "2008:08:07 18:11:31"
Год и неделя в формате ISO YY "-"? "W" W "2008W27", "2008-W28"
Год, неделя в формате ISO и день недели YY "-"? "W" W "-"? [0-7] "2008W273", "2008-W28-3"
MySQL YY "-" MM "-" DD " " HH ":" II ":" SS "2008-08-07 18:11:31"
PostgreSQL: год и день в году YY "."? doy "2008.197", "2008197"
SOAP YY "-" MM "-" DD "T" HH ":" II ":" SS frac tzcorrection? "2008-07-01T22:35:17.02", "2008-07-01T22:35:17.03+08:00"
Unix Timestamp "@" "-"? [0-9]+ "@1215282385"
Метка времени Unix с микросекундами "@" "-"? [0-9]+ "." [0-9]{0,6} "@1607974647.503686"
XMLRPC YY MM DD "T" hh ":" II ":" SS "20080701T22:38:07", "20080701T9:38:07"
XMLRPC (Compact) YY MM DD 't' hh II SS "20080701t223807", "20080701T093807"
WDDX YY "-" mm "-" dd "T" hh ":" ii ":" ss "2008-7-1T9:3:37"

Замечание:

Символ "W" в форматах "Год и неделя в формате ISO" и "Год, неделя в формате ISO и день недели" чувствителен к регистру, символ "W" указывают только в верхнем регистре.

Символ "T" в форматах SOAP, XMLRPC и WDDX также чувствителен к регистру, символ "T" указывают только в верхнем регистре.

Формат "Unix Timestamp" устанавливает часовой пояс в UTC.

Относительные форматы

Страница описывает относительные форматы даты и времени в BNF-подобном синтаксисе, которые понимает парсер классов DateTimeImmutable и DateTime, и функций date_create(), date_create_immutable(), strtotime().

Объекты даты и времени DateTimeImmutable и DateTime форматируют нотацией, которую описывает документация к методу DateTimeInterface::format().

Символы
Описание Формат
dayname (название дня недели) 'sunday' | 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday' | 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
daytext (будние дни — пн–пт, без учёта праздничных дней) 'weekday' | 'weekdays'
number (числа) [+-]?[0-9]+
ordinal (порядковые числительные и относительные указатели) 'first' | 'second' | 'third' | 'fourth' | 'fifth' | 'sixth' | 'seventh' | 'eighth' | 'ninth' | 'tenth' | 'eleventh' | 'twelfth' | 'next' | 'last' | 'previous' | 'this'
reltext (относительные указатели) 'next' | 'last' | 'previous' | 'this'
space (символы пробела и табуляции) [ \t]+
unit (единицы измерения) 'ms' | 'µs' | (( 'msec' | 'millisecond' | 'µsec' | 'microsecond' | 'usec' | 'sec' | 'second' | 'min' | 'minute' | 'hour' | 'day' | 'fortnight' | 'forthnight' | 'month' | 'year') 's'?) | 'weeks' | daytext
Обозначения на основе дней
Формат Описание Примеры
'yesterday' Полночь вчера "yesterday 14:00"
'midnight' Время устанавливается в 00:00:00  
'today' Время устанавливается в 00:00:00  
'now' Текущее время  
'noon' Время устанавливается в 12:00:00 "yesterday noon"
'tomorrow' Полночь завтра  
'back of' hour 15 минут заданного часа "back of 7pm", "back of 15"
'front of' hour Без 15 минут заданный час "front of 5am", "front of 23"
'first day of' Устанавливает первый день текущего месяца. Обычно эту нотацию лучше использовать вместе с названием месяца, следующим за ней, иначе будет учитываться текущий месяц. "first day of January 2008"
'last day of' Устанавливает последний день текущего месяца. Обычно эту нотацию лучше использовать вместе с названием месяца, следующим за ней, иначе будет учитываться текущий месяц. "last day of next month"
ordinal space dayname space 'of' Вычисляет x день недели текущего или заданного месяца. "first sat of July 2008"
'last' space dayname space 'of' Вычисляет последний день недели текущего или заданного месяца. "last sat of July 2008"
number space? (unit | 'week') Вычисляет относительное время при использовании числовых значений периода. "+5 weeks", "12 day", "-7 weekdays"
(ordinal | reltext) space unit Вычисляет относительное время при использовании строковых значений периода. last и previous то же, что и -1, this ни на что не влияет, а next+1. "fifth day", "second month", "last day", "previous year"
'ago' Вычитает все значения из последнего полученного момента времени. "2 days ago", "8 days ago 14:00", "2 months 5 days ago", "2 months ago 5 days", "2 days ago ago"
dayname Перемещается на следующий день указанного дня недели. (Смотрите замечание) "Monday"
reltext space 'week' Разбирает специфичный формат "weekday + last/this/next week". "Monday next week"

Замечание:

Относительные выражения обрабатываются только после неотносительных. Например, "+1 week july 2008" эквивалентно "july 2008 +1 week".

Исключение из этого правила составляют: "yesterday", "midnight", "today", "noon" и "tomorrow". Записи "tomorrow 11:00" и "11:00 tomorrow" отличаются. Если принять сегодняшнюю дату за "July 23rd, 2008", то первая запись возвращает "2008-07-24 11:00", а вторая "2008-07-24 00:00". Причина такого поведения в том, что эти пять выражений влияют непосредственно на время.

Ключевые слова наподобие "first day of" зависят от контекста строки относительного формата. Для строк в статическом методе или функции референтом станет текущая системная метка времени, но методе DateTime::modify() или DateTimeImmutable::modify() референтом станет объект, на котором вызывается метод modify().

Замечание:

Следует обратить внимание на следующие замечания относительно текущего дня недели и дня недели, который указали в строке даты и времени. Текущий день недели вычисляется из независимой части строки даты и времени.

  1. "dayname" не сдвигает дату на другой день. (Например: "Wed July 23rd, 2008" означает "2008-07-23").
  2. "number dayname" не сдвигает дату на другой день. (Например: "1 wednesday july 23rd, 2008" означает "2008-07-23").
  3. "number week dayname" добавляет соответствующее число недель, но не сдвигает дату на другой день. В этом случае имеют место два различных блока "number week" и "dayname". (Например: "+1 week wednesday july 23rd, 2008" означает "2008-07-30").
  4. "ordinal dayname" сдвигает дату на другой день. (Например: "last wednesday july 23rd, 2008" означает "2008-07-30").
  5. "number week ordinal dayname" добавляет число недель, которое соответствует символу числа, а затем сдвигает дату на другой день. В этом случае имеют место два различных блока "number week" и "ordinal dayname". (Например: "+1 week first wednesday july 23rd, 2008" означает "2008-08-06").
  6. "ordinal dayname 'of' " не сдвигает дату на другой день. (Например: "first wednesday of july 23rd, 2008" означает "2008-07-02", потому как определённые фразы с 'of' сбрасывают день месяца на '1' и в этом случае игнорируется '23rd').

Также следует обратить внимание, что "of" в "ordinal space dayname space 'of' " и "'last' space dayname space 'of' " имеет особый смысл.

  1. Устанавливает для дня месяца значение 1.
  2. "ordinal dayname 'of' "не сдвигает дату на другой день. (Например: "first tuesday of july 2008" означает "2008-07-01").
  3. "ordinal dayname" сдвигает дату на другой день. (Например: "first tuesday july 2008" означает "2008-07-08", смотрите также 4-й пункт предыдущего замечания).
  4. "'last' dayname 'of' " получает последний в месяце dayname. (Например: "last wed of july 2008" означает "2008-07-30")
  5. "'last' dayname" получает последний dayname перед текущим днём. (Например: "last wed july 2008" означает "2008-06-25"; "july 2008" устанавливает дату в "2008-07-01", а после "last wed" смещает дату к предыдущей среде, а именно к "2008-06-25").

Замечание:

Относительные значения в месяцах рассчитываются на основе продолжительности месяца. Например, из "+2 month 2011-11-30" получится "2012-01-30". Это связано с тем, что ноябрь состоит из 30 дней, а декабрь из 31 дня, что составляет 61 день.

Замечание:

Под числом (number) подразумевается целое число (integer); десятичная точка (или запятая) рассматривается как разделитель, если указали десятичное число. Например, '+1.5 hours' посчитается как '+1 5 hours', а не '+1 hour +30 minutes'.

Список изменений

Версия Описание
8.4.0 Символы number теперь снова принимают последовательность знаков плюс и минус в записях наподобие +-2, и другие комбинации множественных знаков.
8.2.0 Символы number больше не принимают последовательность знаков плюс и минус, поэтому запись наподобие +-2 недопустима.
7.0.8 Недели начинаются только с понедельника. Раньше разрешалось определять начало недели с воскресенья.

Добавить

Примечания пользователей

Пользователи ещё не добавляли примечания для страницы
To Top