8.5. Типы даты/времени
PostgreSQL поддерживает полный набор типов даты и времени SQL, показанный в Таблице 8.9. Операции, возможные с этими типами данных, описаны в Разделе 9.9. Все даты считаются по Григорианскому календарю, даже для времени до его введения (за дополнительными сведениями обратитесь к Разделу B.6).
Таблица 8.9. Типы даты/времени
Имя | Размер | Описание | Наименьшее значение | Наибольшее значение | Точность |
---|---|---|---|---|---|
timestamp [ ( | 8 байт | дата и время (без часового пояса) | 4713 до н. э. | 294276 н. э. | 1 микросекунда |
timestamp [ ( | 8 байт | дата и время (с часовым поясом) | 4713 до н. э. | 294276 н. э. | 1 микросекунда |
date | 4 байта | дата (без времени суток) | 4713 до н. э. | 5874897 н. э. | 1 день |
time [ ( | 8 байт | время суток (без даты) | 00:00:00 | 24:00:00 | 1 микросекунда |
time [ ( | 12 байт | время дня (без даты), с часовым поясом | 00:00:00+1559 | 24:00:00-1559 | 1 микросекунда |
interval [ | 16 байт | временной интервал | -178000000 лет | 178000000 лет | 1 микросекунда |
Примечание
Стандарт SQL требует, чтобы тип timestamp
подразумевал timestamp without time zone
(время без часового пояса), и PostgreSQL следует этому. Для краткости timestamp with time zone
можно записать как timestamptz
; это расширение PostgreSQL.
Типы time
, timestamp
и interval
принимают необязательное значение точности p
, определяющее, сколько знаков после запятой должно сохраняться в секундах. По умолчанию точность не ограничивается. Допустимые значения p
лежат в интервале от 0 до 6.
Тип interval
дополнительно позволяет ограничить набор сохраняемых полей следующими фразами:
YEAR MONTH DAY HOUR MINUTE SECOND YEAR TO MONTH DAY TO HOUR DAY TO MINUTE DAY TO SECOND HOUR TO MINUTE HOUR TO SECOND MINUTE TO SECOND
Заметьте, что если указаны и поля
, и точность p
, указание поля
должно включать SECOND
, так как точность применима только к секундам.
Тип time with time zone
определён стандартом SQL, но в его определении описаны свойства сомнительной ценности. В большинстве случаев сочетание типов date
, time
, timestamp without time zone
и timestamp with time zone
удовлетворяет все потребности в функциональности дат/времени, возникающие в приложениях.
8.5.1. Ввод даты/времени
Значения даты и времени принимаются практически в любом разумном формате, включая ISO 8601, SQL-совместимый, традиционный формат POSTGRES и другие. В некоторых форматах порядок даты, месяца и года во вводимой дате неоднозначен и поэтому поддерживается явное определение формата. Для этого предназначен параметр DateStyle. Когда он имеет значение MDY
, выбирается интерпретация месяц-день-год, значению DMY
соответствует день-месяц-год, а YMD
— год-месяц-день.
PostgreSQL обрабатывает вводимые значения даты/времени более гибко, чем того требует стандарт SQL. Точные правила разбора даты/времени и распознаваемые текстовые поля, в том числе названия месяцев, дней недели и часовых поясов описаны в Приложении B.
Помните, что любые вводимые значения даты и времени нужно заключать в апострофы, как текстовые строки. За дополнительной информацией обратитесь к Подразделу 4.1.2.7. SQL предусматривает следующий синтаксис:
тип
[ (p
) ] 'значение
'
Здесь p
— необязательное указание точности, определяющее число знаков после точки в секундах. Точность может быть определена для типов time
, timestamp
и interval
в интервале от 0 до 6. Если в определении константы точность не указана, она считается равной точности значения в строке (но не больше 6 цифр).
8.5.1.1. Даты
В Таблице 8.10 приведены некоторые допустимые значения типа date
.
Таблица 8.10. Вводимые даты
Пример | Описание |
---|---|
1999-01-08 | ISO 8601; 8 января в любом режиме (рекомендуемый формат) |
January 8, 1999 | воспринимается однозначно в любом режиме datestyle |
1/8/1999 | 8 января в режиме MDY и 1 августа в режиме DMY |
1/18/1999 | 18 января в режиме MDY ; недопустимая дата в других режимах |
01/02/03 | 2 января 2003 г. в режиме MDY ; 1 февраля 2003 г. в режиме DMY и 3 февраля 2001 г. в режиме YMD |
1999-Jan-08 | 8 января в любом режиме |
Jan-08-1999 | 8 января в любом режиме |
08-Jan-1999 | 8 января в любом режиме |
99-Jan-08 | 8 января в режиме YMD ; ошибка в других режимах |
08-Jan-99 | 8 января; ошибка в режиме YMD |
Jan-08-99 | 8 января; ошибка в режиме YMD |
19990108 | ISO 8601; 8 января 1999 в любом режиме |
990108 | ISO 8601; 8 января 1999 в любом режиме |
1999.008 | год и день года |
J2451187 | юлианский день |
January 8, 99 BC | 99 до н. э. |
8.5.1.2. Время
Для хранения времени суток без даты предназначены типы time [ (
и p
) ] without time zonetime [ (
. Тип p
) ] with time zonetime
без уточнения эквивалентен типу time without time zone
.
Допустимые вводимые значения этих типов состоят из записи времени суток и необязательного указания часового пояса. (См. Таблицу 8.11 и Таблицу 8.12.) Если в значении для типа time without time zone
указывается часовой пояс, он просто игнорируется. Так же будет игнорироваться дата, если её указать, за исключением случаев, когда в указанном часовом поясе принят переход на летнее время, например America/New_York
. В данном случае указать дату необходимо, чтобы система могла определить, применяется ли обычное или летнее время. Соответствующее смещение часового пояса записывается в значении time with time zone
и выводится без изменений, оно не привязано к активному часовому поясу.
Таблица 8.11. Вводимое время
Пример | Описание |
---|---|
04:05:06.789 | ISO 8601 |
04:05:06 | ISO 8601 |
04:05 | ISO 8601 |
040506 | ISO 8601 |
04:05 AM | то же, что и 04:05; AM не меняет значение времени |
04:05 PM | то же, что и 16:05; часы должны быть <= 12 |
04:05:06.789-8 | ISO 8601, с часовым поясом в виде смещения от UTC |
04:05:06-08:00 | ISO 8601, с часовым поясом в виде смещения от UTC |
04:05-08:00 | ISO 8601, с часовым поясом в виде смещения от UTC |
040506-08 | ISO 8601, с часовым поясом в виде смещения от UTC |
040506+0730 | ISO 8601, с часовым поясом, задаваемым нецелочисленным смещением от UTC |
040506+07:30:00 | смещение от UTC, заданное до секунд (не допускается в ISO 8601) |
04:05:06 PST | часовой пояс задаётся аббревиатурой |
2003-04-12 04:05:06 America/New_York | часовой пояс задаётся полным названием |
Таблица 8.12. Вводимый часовой пояс
Пример | Описание |
---|---|
PST | аббревиатура (Pacific Standard Time, Стандартное тихоокеанское время) |
America/New_York | полное название часового пояса |
PST8PDT | указание часового пояса в стиле POSIX |
-8:00:00 | смещение часового пояса PST от UTC |
-8:00 | смещение часового пояса PST от UTC (расширенный формат ISO 8601) |
-800 | смещение часового пояса PST от UTC (стандартный формат ISO 8601) |
-8 | смещение часового пояса PST от UTC (стандартный формат ISO 8601) |
zulu | принятое у военных сокращение UTC |
z | краткая форма zulu (также определена в ISO 8601) |
Подробнее узнать о том, как указывается часовой пояс, можно в Подразделе 8.5.3.
8.5.1.3. Даты и время
Допустимые значения типов timestamp состоят из записи даты и времени, после которого может указываться часовой пояс и необязательное уточнение AD
или BC
, определяющее эпоху до нашей эры и нашу эру соответственно. (AD
/BC
можно указать и перед часовым поясом, но предпочтительнее первый вариант.) Таким образом:
1999-01-08 04:05:06
и
1999-01-08 04:05:06 -8:00
допустимые варианты, соответствующие стандарту ISO 8601. В дополнение к этому поддерживается распространённый формат:
January 8 04:05:06 1999 PST
Стандарт SQL различает константы типов timestamp without time zone
и timestamp with time zone
по знаку «+» или «-» и смещению часового пояса, добавленному после времени. Следовательно, согласно стандарту, записи
TIMESTAMP '2004-10-19 10:23:54'
должен соответствовать тип timestamp without time zone
, а
TIMESTAMP '2004-10-19 10:23:54+02'
тип timestamp with time zone
. PostgreSQL никогда не анализирует содержимое текстовой строки, чтобы определить тип значения, и поэтому обе записи будут обработаны как значения типа timestamp without time zone
. Чтобы текстовая константа обрабатывалась как timestamp with time zone
, укажите этот тип явно:
TIMESTAMP WITH TIME ZONE '2004-10-19 10:23:54+02'
В константе типа timestamp without time zone
PostgreSQL просто игнорирует часовой пояс. То есть результирующее значение вычисляется только из полей даты/времени и не подстраивается под указанный часовой пояс.
Значения timestamp with time zone
внутри всегда хранятся в UTC (Universal Coordinated Time, Всемирное скоординированное время или время по Гринвичу, GMT). Вводимое значение, в котором явно указан часовой пояс, переводится в UTC с учётом смещения данного часового пояса. Если во входной строке не указан часовой пояс, подразумевается часовой пояс, заданный системным параметром TimeZone и время так же пересчитывается в UTC со смещением timezone
.
Когда значение timestamp with time zone
выводится, оно всегда преобразуется из UTC в текущий часовой пояс timezone
и отображается как локальное время. Чтобы получить время для другого часового пояса, нужно либо изменить timezone
, либо воспользоваться конструкцией AT TIME ZONE
(см. Подраздел 9.9.4).
В преобразованиях между timestamp without time zone
и timestamp with time zone
обычно предполагается, что значение timestamp without time zone
содержит местное время (для часового пояса timezone
). Другой часовой пояс для преобразования можно задать с помощью AT TIME ZONE
.
8.5.1.4. Специальные значения
PostgreSQL для удобства поддерживает несколько специальных значений даты/времени, перечисленных в Таблице 8.13. Значения infinity
и -infinity
имеют особое представление в системе и они отображаются в том же виде, тогда как другие варианты при чтении преобразуются в значения даты/времени. (В частности, now
и подобные строки преобразуются в актуальные значения времени в момент чтения.) Чтобы использовать эти значения в качестве констант в командах SQL, их нужно заключать в апострофы.
Таблица 8.13. Специальные значения даты/времени
Вводимая строка | Допустимые типы | Описание |
---|---|---|
epoch | date , timestamp | 1970-01-01 00:00:00+00 (точка отсчёта времени в Unix) |
infinity | date , timestamp | время после максимальной допустимой даты |
-infinity | date , timestamp | время до минимальной допустимой даты |
now | date , time , timestamp | время начала текущей транзакции |
today | date , timestamp | время начала текущих суток (00:00 ) |
tomorrow | date , timestamp | время начала следующих суток (00:00 ) |
yesterday | date , timestamp | время начала предыдущих суток (00:00 ) |
allballs | time | 00:00:00.00 UTC |
Для получения текущей даты/времени соответствующего типа можно также использовать следующие SQL-совместимые функции: CURRENT_DATE
, CURRENT_TIME
, CURRENT_TIMESTAMP
, LOCALTIME
и LOCALTIMESTAMP
. (См. Подраздел 9.9.5.) Заметьте, что во входных строках эти SQL-функции не распознаются.
Внимание
Входные значения now
, today
, tomorrow
и yesterday
вполне корректно работают в интерактивных SQL-командах, но когда команды сохраняются для последующего выполнения, например в подготовленных операторах, представлениях или определениях функций, их поведение может быть неожиданным. Такая строка может преобразоваться в конкретное значение времени, которое затем будет использоваться гораздо позже момента, когда оно было получено. В таких случаях следует использовать одну из SQL-функций. Например, CURRENT_DATE + 1
будет работать надёжнее, чем 'tomorrow'::date
.
8.5.2. Вывод даты/времени
В качестве выходного формата типов даты/времени можно использовать один из четырёх стилей: ISO 8601, SQL (Ingres), традиционный формат POSTGRES (формат date в Unix) или German. По умолчанию выбран формат ISO. (Стандарт SQL требует, чтобы использовался именно ISO 8601. Другой формат называется «SQL» исключительно по историческим причинам.) Примеры всех стилей вывода перечислены в Таблице 8.14. Вообще со значениями типов date
и time
выводилась бы только часть даты или времени из показанных примеров, но со стилем POSTGRES значение даты без времени выводится в формате ISO.
Таблица 8.14. Стили вывода даты/время
Стиль | Описание | Пример |
---|---|---|
ISO | ISO 8601, стандарт SQL | 1997-12-17 07:37:16-08 |
SQL | традиционный стиль | 12/17/1997 07:37:16.00 PST |
Postgres | изначальный стиль | Wed Dec 17 07:37:16 1997 PST |
German | региональный стиль | 17.12.1997 07:37:16.00 PST |
Примечание
ISO 8601 указывает, что дата должна отделяться от времени буквой T
в верхнем регистре. PostgreSQL принимает этот формат при вводе, но при выводе вставляет вместо T
пробел, как показано выше. Это сделано для улучшения читаемости и для совместимости с RFC 3339 и другими СУБД.
В стилях SQL и POSTGRES день выводится перед месяцем, если установлен порядок DMY, а в противном случае месяц выводится перед днём. (Как этот параметр также влияет на интерпретацию входных значений, описано в Подразделе 8.5.1) Соответствующие примеры показаны в Таблице 8.15.
Таблица 8.15. Соглашения о порядке компонентов даты
Параметр datestyle | Порядок при вводе | Пример вывода |
---|---|---|
SQL, DMY | день /месяц /год | 17/12/1997 15:37:16.00 CET |
SQL, MDY | месяц /день /год | 12/17/1997 07:37:16.00 PST |
Postgres, DMY | день /месяц /год | Wed 17 Dec 07:37:16 1997 PST |
В формате ISO часовой пояс всегда отображается в виде числового смещения со знаком относительно всемирного координированного времени (UTC); для зон к востоку от Гринвича знак смещения положительный. Смещение будет отображаться как hh
(только часы), если оно задаётся целым числом часов, как hh
:mm
, если оно задаётся целым числом минут, или как hh
:mm
:ss
. (Третий вариант невозможен в современных стандартах часовых поясов, но он может понадобиться при работе с отметками времени, предшествующими принятию стандартизированных часовых поясов.) В других форматах даты часовой пояс отображается как буквенное сокращение, если оно принято в текущем поясе. В противном случае он отображается как числовое смещение со знаком в стандартном формате ISO 8601 (hh
или hhmm
).
Стиль даты/времени пользователь может выбрать с помощью команды SET datestyle
, параметра DateStyle в файле конфигурации postgresql.conf
или переменной окружения PGDATESTYLE
на сервере или клиенте.
Для большей гибкости при форматировании выводимой даты/времени можно использовать функцию to_char
(см. Раздел 9.8).
8.5.3. Часовые пояса
Часовые пояса и правила их применения определяются, как вы знаете, не только по географическим, но и по политическим соображениям. Часовые пояса во всём мире были более-менее стандартизированы в начале прошлого века, но они продолжают претерпевать изменения, в частности это касается перехода на летнее время. Для расчёта времени в прошлом PostgreSQL получает исторические сведения о правилах часовых поясов из распространённой базы данных IANA (Olson). Для будущего времени предполагается, что в заданном часовом поясе будут продолжать действовать последние принятые правила.
PostgreSQL стремится к совместимости со стандартом SQL в наиболее типичных случаях. Однако стандарт SQL допускает некоторые странности при смешивании типов даты и времени. Две очевидные проблемы:
Хотя для типа
date
часовой пояс указать нельзя, это можно сделать для типаtime
. В реальности это не очень полезно, так как без даты нельзя точно определить смещение при переходе на летнее время.По умолчанию часовой пояс задаётся постоянным смещением от UTC. Это также не позволяет учесть летнее время при арифметических операций с датами, пересекающими границы летнего времени.
Поэтому мы советуем использовать часовой пояс с типами, включающими и время, и дату. Мы не рекомендуем использовать тип time with time zone
(хотя PostgreSQL поддерживает его для старых приложений и совместимости со стандартом SQL). Для типов, включающих только дату или только время, в PostgreSQL предполагается местный часовой пояс.
Все значения даты и времени с часовым поясом представляются внутри в UTC, а при передаче клиентскому приложению они переводятся в местное время, при этом часовой пояс по умолчанию определяется параметром конфигурации TimeZone.
PostgreSQL позволяет задать часовой пояс тремя способами:
Полное название часового пояса, например
America/New_York
. Все допустимые названия перечислены в представленииpg_timezone_names
(см. Раздел 52.94). Определения часовых поясов PostgreSQL берёт из широко распространённой базы IANA, так что имена часовых поясов PostgreSQL будут воспринимать и другие приложения.Аббревиатура часового пояса, например
PST
. Такое определение просто задаёт смещение от UTC, в отличие от полных названий поясов, которые кроме того подразумевают и правила перехода на летнее время. Распознаваемые аббревиатуры перечислены в представленииpg_timezone_abbrevs
(см. Раздел 52.93). Аббревиатуры можно использовать во вводимых значениях даты/времени и в оператореAT TIME ZONE
, но не в параметрах конфигурации TimeZone и log_timezone.Помимо аббревиатур и названий часовых поясов PostgreSQL принимает указания часовых поясов в стиле POSIX, как описано в Разделе B.5. Этот вариант обычно менее предпочтителен, чем использование именованного часового пояса, но он может быть единственным возможным, если для нужного часового пояса нет записи в базе данных IANA.
Вкратце, различие между аббревиатурами и полными названиями заключаются в следующем: аббревиатуры представляют определённый сдвиг от UTC, а полное название подразумевает ещё и местное правило по переходу на летнее время, то есть, возможно, два сдвига от UTC. Например, 2014-06-04 12:00 America/New_York
представляет полдень по местному времени в Нью-Йорк, что для данного дня было бы летним восточным временем (EDT или UTC-4). Так что 2014-06-04 12:00 EDT
обозначает тот же момент времени. Но 2014-06-04 12:00 EST
задаёт стандартное восточное время (UTC-5), не зависящее о того, действовало ли летнее время в этот день.
Мало того, в некоторых юрисдикциях одна и та же аббревиатура часового пояса означала разные сдвиги UTC в разное время; например, аббревиатура московского времени MSK
несколько лет означала UTC+3, а затем стала означать UTC+4. PostgreSQL обрабатывает такие аббревиатуры в соответствии с их значениями на заданную дату, но, как и с примером выше EST
, это не обязательно будет соответствовать местному гражданскому времени в этот день.
Независимо от формы, регистр в названиях и аббревиатурах часовых поясов не важен. (В PostgreSQL до версии 8.2 он где-то имел значение, а где-то нет.)
Ни названия, ни аббревиатуры часовых поясов, не зашиты в самом сервере; они считываются из файлов конфигурации, находящихся в путях .../share/timezone/
и .../share/timezonesets/
относительно каталога установки (см. Раздел B.4).
Параметр конфигурации TimeZone можно установить в postgresql.conf
или любым другим стандартным способом, описанным в Главе 20. Часовой пояс может быть также определён следующими специальными способами:
Часовой пояс для текущего сеанса можно установить с помощью SQL-команды
SET TIME ZONE
. Это альтернативная запись командыSET TIMEZONE TO
, более соответствующая SQL-стандарту.Если установлена переменная окружения
PGTZ
, клиенты libpq используют её значение, выполняя при подключении к серверу командуSET TIME ZONE
.
8.5.4. Ввод интервалов
Значения типа interval
могут быть записаны в следующей расширенной форме:
[@]количество
единица
[количество
единица
...] [направление
]
где количество
— это число (возможно, со знаком); единица
— одно из значений: microsecond
, millisecond
, second
, minute
, hour
, day
, week
, month
, year
, decade
, century
, millennium
(которые обозначают соответственно микросекунды, миллисекунды, секунды, минуты, часы, дни, недели, месяцы, годы, десятилетия, века и тысячелетия), либо эти же слова во множественном числе, либо их сокращения; направление
может принимать значение ago
(назад) или быть пустым. Знак @
является необязательным. Все заданные величины различных единиц суммируются вместе с учётом знака чисел. Указание ago
меняет знак всех полей на противоположный. Этот синтаксис также используется при выводе интервала, если параметр IntervalStyle имеет значение postgres_verbose
.
Количества дней, часов, минут и секунд можно определить, не указывая явно соответствующие единицы. Например, запись '1 12:59:10'
равнозначна '1 day 12 hours 59 min 10 sec'
. Сочетание года и месяца также можно записать через минус; например '200-10'
означает то, же что и '200 years 10 months'
. (На самом деле только эти краткие формы разрешены стандартом SQL и они используются при выводе, когда IntervalStyle
имеет значение sql_standard
.)
Интервалы можно также записывать в виде, определённом в ISO 8601, либо в «формате с кодами», описанном в разделе 4.4.3.2 этого стандарта, либо в «альтернативном формате», описанном в разделе 4.4.3.3. Формат с кодами выглядит так:
Pколичество
единица
[количество
единица
...] [ T [количество
единица
...]]
Строка должна начинаться с символа P
и может включать также T
перед временем суток. Допустимые коды единиц перечислены в Таблице 8.16. Коды единиц можно опустить или указать в любом порядке, но компоненты времени суток должны идти после символа T
. В частности, значение кода M
зависит от того, располагается ли он до или после T
.
Таблица 8.16. Коды единиц временных интервалов ISO 8601
Код | Значение |
---|---|
Y | годы |
M | месяцы (в дате) |
W | недели |
D | дни |
H | часы |
M | минуты (во времени) |
S | секунды |
В альтернативном формате:
P [год
-месяц
-день
] [ Tчасы
:минуты
:секунды
]
строка должна начинаться с P
, а T
разделяет компоненты даты и времени. Значения выражаются числами так же, как и в датах ISO 8601.
При записи интервальной константы с указанием полей
или присваивании столбцу типа interval строки с полями
, интерпретация непомеченных величин зависит от полей
. Например, INTERVAL '1' YEAR
воспринимается как 1 год, а INTERVAL '1'
— как 1 секунда. Кроме того, значения «справа» от меньшего значащего поля, заданного в определении полей
, просто отбрасываются. Например, в записи INTERVAL '1 day 2:03:04' HOUR TO MINUTE
будут отброшены секунды, но не день.
Согласно стандарту SQL, все компоненты значения interval должны быть одного знака, и ведущий минус применяется ко всем компонентам; например, минус в записи '-1 2:03:04'
применяется и к дню, и к часам/минутам/секундам. PostgreSQL позволяет задавать для разных компонентов разные знаки и традиционно обрабатывает знак каждого компонента в текстовом представлении отдельно от других, так что в данном случае часы/минуты/секунды будут считаться положительными. Если параметр IntervalStyle
имеет значение sql_standard
, ведущий знак применяется ко всем компонентам (но только если они не содержат знаки явно). В противном случае действуют традиционные правила PostgreSQL. Во избежание неоднозначности рекомендуется добавлять знак к каждому компоненту с отрицательным значением.
Значения interval
хранятся в виде трёх целочисленных полей: месяцы, дни и микросекунды. Эти поля хранятся отдельно, поскольку количество дней в месяце варьируется, а день может состоять из 23 или 25 часов при переходе на летнее/зимнее время. Входная строка интервала, в которой используются другие единицы измерения, нормализуется в этот формат, а затем стандартизированным образом реконструируется для вывода, например:
SELECT '2 years 15 months 100 weeks 99 hours 123456789 milliseconds'::interval; interval --------------------------------------- 3 years 3 mons 700 days 133:17:36.789
Здесь недели, под которыми понимаются «7 дней», были сохранены отдельно, а меньшие и большие единицы измерения времени были объединены и нормализованы.
Значения полей могут содержать дробную часть, например '1.5 weeks'
или '01:02:03.45'
. Однако поскольку interval
содержит только целые единицы, дробные значения должны быть преобразованы в более мелкие единицы. Дробные части единиц, превышающих месяцы, усекаются до целого числа месяцев, например '1.5 years'
преобразуется в '1 year 6 mons'
. Дробные части недель и дней пересчитываются в целое число дней и микросекунд, из расчёта, что в месяце 30 дней, а в сутках — 24 часа, например, '1.75 months'
становится 1 mon 22 days 12:00:00
. На выходе только секунды могут иметь дробную часть.
В Таблице 8.17 показано несколько примеров допустимых вводимых значений типа interval
.
Таблица 8.17. Ввод интервалов
Пример | Описание |
---|---|
1-2 | Стандартный формат SQL: 1 год и 2 месяца |
3 4:05:06 | Стандартный формат SQL: 3 дня 4 часа 5 минут 6 секунд |
1 year 2 months 3 days 4 hours 5 minutes 6 seconds | Традиционный формат Postgres: 1 год 2 месяца 3 дня 4 часа 5 минут 6 секунд |
P1Y2M3DT4H5M6S | «Формат с кодами» ISO 8601: то же значение, что и выше |
P0001-02-03T04:05:06 | «Альтернативный формат» ISO 8601: то же значение, что и выше |
8.5.5. Вывод интервалов
Как объяснялось ранее, PostgreSQL хранит значения interval
в виде месяцев, дней и микросекунд. При выводе значение месяцев преобразуется в годы и месяцы путём деления на 12. Значение в днях отображается как есть. Значение в микросекундах преобразуется в часы, минуты, секунды и доли секунды. Таким образом, месяцы, минуты и секунды никогда не будут выводиться вне диапазонов 0–11, 0–59 и 0–59 соответственно, тогда как отображаемые значения в годах, днях и часах могут быть довольно большими. (Чтобы перенести большие значения дней и часов в следующее поле, можно использовать функции justify_days
и justify_hours
.)
Формат вывода типа interval может определяться одним из четырёх стилей: sql_standard
, postgres
, postgres_verbose
и iso_8601
. Выбрать нужный стиль позволяет команда SET intervalstyle
(по умолчанию выбран postgres
). Примеры форматов разных стилей показаны в Таблице 8.18.
Стиль sql_standard
выдаёт результат, соответствующий стандарту SQL, если значение интервала удовлетворяет ограничениям стандарта (и содержит либо только год и месяц, либо только день и время, и при этом все его компоненты одного знака). В противном случае выводится год-месяц, за которым идёт дата-время, а в компоненты для однозначности явно добавляются знаки.
Вывод в стиле postgres
соответствует формату, который был принят в PostgreSQL до версии 8.4, когда параметр DateStyle имел значение ISO
.
Вывод в стиле postgres_verbose
соответствует формату, который был принят в PostgreSQL до версии 8.4, когда значением параметром DateStyle
было не ISO
.
Вывод в стиле iso_8601
соответствует «формату с кодами» описанному в разделе 4.4.3.2 формата ISO 8601.
Таблица 8.18. Примеры стилей вывода интервалов
Стиль | Интервал год-месяц | Интервал день-время | Смешанный интервал |
---|---|---|---|
sql_standard | 1-2 | 3 4:05:06 | -1-2 +3 -4:05:06 |
postgres | 1 year 2 mons | 3 days 04:05:06 | -1 year -2 mons +3 days -04:05:06 |
postgres_verbose | @ 1 year 2 mons | @ 3 days 4 hours 5 mins 6 secs | @ 1 year 2 mons -3 days 4 hours 5 mins 6 secs ago |
iso_8601 | P1Y2M | P3DT4H5M6S | P-1Y-2M3DT-4H-5M-6S |