8.5. Типы даты/времени

Postgres Pro поддерживает полный набор типов даты и времени SQL, показанный в Таблице 8.9. Операции, возможные с этими типами данных, описаны в Разделе 9.9. Все даты считаются по Григорианскому календарю, даже для времени до его введения (за дополнительными сведениями обратитесь к Разделу B.6).

Таблица 8.9. Типы даты/времени

ИмяРазмерОписаниеНаименьшее значениеНаибольшее значениеТочность
timestamp [ (p) ] [ without time zone ]8 байтдата и время (без часового пояса)4713 до н. э.294276 н. э.1 микросекунда / 14 цифр
timestamp [ (p) ] with time zone8 байтдата и время (с часовым поясом)4713 до н. э.294276 н. э.1 микросекунда / 14 цифр
date4 байтадата (без времени суток)4713 до н. э.5874897 н. э.1 день
time [ (p) ] [ without time zone ]8 байтвремя суток (без даты)00:00:0024:00:001 микросекунда / 14 цифр
time [ (p) ] with time zone12 байттолько время суток (с часовым поясом)00:00:00+155924:00:00-15591 микросекунда / 14 цифр
interval [ поля ] [ (p) ]16 байтвременной интервал-178000000 лет178000000 лет1 микросекунда / 14 цифр

Примечание

Стандарт SQL требует, чтобы тип timestamp подразумевал timestamp without time zone (время без часового пояса), и Postgres Pro следует этому. Для краткости timestamp with time zone можно записать как timestamptz; это расширение Postgres Pro.

Типы time, timestamp и interval принимают необязательное значение точности p, определяющее, сколько знаков после запятой должно сохраняться в секундах. По умолчанию точность не ограничивается. Для типов timestamp и interval p может принимать значения от 0 до 6.

Примечание

Когда значения timestamp хранятся в восьмибайтных целых (сейчас по умолчанию это так), на всём интервале значений обеспечивается точность в микросекундах. Если же значения этого типа сохраняются в числах двойной точности с плавающей точкой (устаревший вариант компиляции), фактический предел точности может быть меньше 6. Значения timestamp сохраняются в секундах до или после полуночи 1 января 2000 г. Когда при этом используются числа с плавающей точкой, микросекундная точность достигается для дат в пределах нескольких лет от этой даты, а при удалении от неё точность теряется. Однако заметьте, что даты в числах с плавающей точкой позволяют представить больший диапазон timestamp, чем было показано выше: от 4713 до н. э. до 5874897 н. э.

В зависимости от того же варианта компиляции, типы time и interval могут сохраняться в виде чисел с плавающей точкой или в восьмибайтных целых. В случае с плавающей точкой при больших значениях interval точность уменьшается.

Для типа time p может принимать значения от 0 до 6 при хранении типа в восьмибайтном целом и от 0 до 10 при хранении в числе с плавающей точкой.

Тип 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 удовлетворяет все потребности в функционале дат/времени, возникающие в приложениях.

Типы abstime и reltime имеют меньшую точность и предназначены для внутреннего использования. Эти типы не рекомендуется использовать в обычных приложениях; их может не быть в будущих версиях.

8.5.1. Ввод даты/времени

Значения даты и времени принимаются практически в любом разумном формате, включая ISO 8601, SQL-совместимый, традиционный формат POSTGRES и другие. В некоторых форматах порядок даты, месяца и года во вводимой дате неоднозначен и поэтому поддерживается явное определение формата. Для этого предназначен параметр DateStyle. Когда он имеет значение MDY, выбирается интерпретация месяц-день-год, значению DMY соответствует день-месяц-год, а YMD — год-месяц-день.

Postgres Pro обрабатывает вводимые значения даты/времени более гибко, чем того требует стандарт SQL. Точные правила разбора даты/времени и распознаваемые текстовые поля, в том числе названия месяцев, дней недели и часовых поясов описаны в Приложении B.

Помните, что любые вводимые значения даты и времени нужно заключать в апострофы, как текстовые строки. За дополнительной информацией обратитесь к Подразделу 4.1.2.7. SQL предусматривает следующий синтаксис:

тип [ (p) ] 'значение'

Здесь p — необязательное указание точности, определяющее число знаков после точки в секундах. Точность может быть определена для типов time, timestamp и interval в пределах, описанных выше. Если в определении константы точность не указана, она считается равной точности значения в строке.

8.5.1.1. Даты

В Таблице 8.10 приведены некоторые допустимые значения типа date.

Таблица 8.10. Вводимые даты

ПримерОписание
1999-01-08ISO 8601; 8 января в любом режиме (рекомендуемый формат)
January 8, 1999воспринимается однозначно в любом режиме datestyle
1/8/19998 января в режиме MDY и 1 августа в режиме DMY
1/18/199918 января в режиме MDY; недопустимая дата в других режимах
01/02/032 января 2003 г. в режиме MDY; 1 февраля 2003 г. в режиме DMY и 3 февраля 2001 г. в режиме YMD
1999-Jan-088 января в любом режиме
Jan-08-19998 января в любом режиме
08-Jan-19998 января в любом режиме
99-Jan-088 января в режиме YMD; ошибка в других режимах
08-Jan-998 января; ошибка в режиме YMD
Jan-08-998 января; ошибка в режиме YMD
19990108ISO 8601; 8 января 1999 в любом режиме
990108ISO 8601; 8 января 1999 в любом режиме
1999.008год и день года
J2451187юлианский день
January 8, 99 BC99 до н. э.

8.5.1.2. Время

Для хранения времени суток без даты предназначены типы time [ (p) ] without time zone и time [ (p) ] with time zone. Тип time без уточнения эквивалентен типу time without time zone.

Допустимые вводимые значения этих типов состоят из записи времени суток и необязательного указания часового пояса. (См. Таблицу 8.11 и Таблицу 8.12.) Если в значении для типа time without time zone указывается часовой пояс, он просто игнорируется. Так же будет игнорироваться дата, если её указать, за исключением случаев, когда в указанном часовом поясе принят переход на летнее время, например America/New_York. В данном случае указать дату необходимо, чтобы система могла определить, применяется ли обычное или летнее время. Соответствующее смещение часового пояса записывается в значении time with time zone.

Таблица 8.11. Вводимое время

ПримерОписание
04:05:06.789ISO 8601
04:05:06ISO 8601
04:05ISO 8601
040506ISO 8601
04:05 AMто же, что и 04:05; AM не меняет значение времени
04:05 PMто же, что и 16:05; часы должны быть <= 12
04:05:06.789-8ISO 8601, с часовым поясом в виде смещения от UTC
04:05:06-08:00ISO 8601, с часовым поясом в виде смещения от UTC
04:05-08:00ISO 8601, с часовым поясом в виде смещения от UTC
040506-08ISO 8601, с часовым поясом в виде смещения от UTC
040506+0730ISO 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. Postgres Pro никогда не анализирует содержимое текстовой строки, чтобы определить тип значения, и поэтому обе записи будут обработаны как значения типа timestamp without time zone. Чтобы текстовая константа обрабатывалась как timestamp with time zone, укажите этот тип явно:

TIMESTAMP WITH TIME ZONE '2004-10-19 10:23:54+02'

В константе типа timestamp without time zone Postgres Pro просто игнорирует часовой пояс. То есть результирующее значение вычисляется только из полей даты/времени и не подстраивается под указанный часовой пояс.

Значения 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.3).

В преобразованиях между timestamp without time zone и timestamp with time zone обычно предполагается, что значение timestamp without time zone содержит местное время (для часового пояса timezone). Другой часовой пояс для преобразования можно задать с помощью AT TIME ZONE.

8.5.1.4. Специальные значения

Postgres Pro для удобства поддерживает несколько специальных значений даты/времени, перечисленных в Таблице 8.13. Значения infinity и -infinity имеют особое представление в системе и они отображаются в том же виде, тогда как другие варианты при чтении преобразуются в значения даты/времени. (В частности, now и подобные строки преобразуются в актуальные значения времени в момент чтения.) Чтобы использовать эти значения в качестве констант в командах SQL, их нужно заключать в апострофы.

Таблица 8.13. Специальные значения даты/времени

Вводимая строкаДопустимые типыОписание
epochdate, timestamp1970-01-01 00:00:00+00 (точка отсчёта времени в Unix)
infinitydate, timestampвремя после максимальной допустимой даты
-infinitydate, timestampвремя до минимальной допустимой даты
nowdate, time, timestampвремя начала текущей транзакции
todaydate, timestampвремя начала текущих суток (00:00)
tomorrowdate, timestampвремя начала следующих суток (00:00)
yesterdaydate, timestampвремя начала предыдущих суток (00:00)
allballstime00:00:00.00 UTC

Для получения текущей даты/времени соответствующего типа можно также использовать следующие SQL-совместимые функции: CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP, LOCALTIME и LOCALTIMESTAMP. (См. Подраздел 9.9.4.) Заметьте, что во входных строках эти 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. Стили вывода даты/время

СтильОписаниеПример
ISOISO 8601, стандарт SQL1997-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 в верхнем регистре. Postgres Pro принимает этот формат при вводе, но при выводе вставляет вместо 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. Часовые пояса

Часовые пояса и правила их применения определяются, как вы знаете, не только по географическим, но и по политическим соображениям. Часовые пояса во всём мире были более-менее стандартизированы в начале прошлого века, но они продолжают претерпевать изменения, в частности это касается перехода на летнее время. Для расчёта времени в прошлом Postgres Pro получает исторические сведения о правилах часовых поясов из распространённой базы данных IANA (Olson). Для будущего времени предполагается, что в заданном часовом поясе будут продолжать действовать последние принятые правила.

Postgres Pro стремится к совместимости со стандартом SQL в наиболее типичных случаях. Однако стандарт SQL допускает некоторые странности при смешивании типов даты и времени. Две очевидные проблемы:

  • Хотя для типа date часовой пояс указать нельзя, это можно сделать для типа time. В реальности это не очень полезно, так как без даты нельзя точно определить смещение при переходе на летнее время.

  • По умолчанию часовой пояс задаётся постоянным смещением от UTC. Это также не позволяет учесть летнее время при арифметических операций с датами, пересекающими границы летнего времени.

Поэтому мы советуем использовать часовой пояс с типами, включающими и время, и дату. Мы не рекомендуем использовать тип time with time zone (хотя Postgres Pro поддерживает его для старых приложений и совместимости со стандартом SQL). Для типов, включающих только дату или только время, в Postgres Pro предполагается местный часовой пояс.

Все значения даты и времени с часовым поясом представляются внутри в UTC, а при передаче клиентскому приложению они переводятся в местное время, при этом часовой пояс по умолчанию определяется параметром конфигурации TimeZone.

Postgres Pro позволяет задать часовой пояс тремя способами:

  • Полное название часового пояса, например America/New_York. Все допустимые названия перечислены в представлении pg_timezone_names (см. Раздел 50.80). Определения часовых поясов Postgres Pro берёт из широко распространённой базы IANA, так что имена часовых поясов Postgres Pro будут воспринимать и другие приложения.

  • Аббревиатура часового пояса, например PST. Такое определение просто задаёт смещение от UTC, в отличие от полных названий поясов, которые кроме того подразумевают и правила перехода на летнее время. Распознаваемые аббревиатуры перечислены в представлении pg_timezone_abbrevs (см. Раздел 50.79). Аббревиатуры можно использовать во вводимых значениях даты/времени и в операторе AT TIME ZONE, но не в параметрах конфигурации TimeZone и log_timezone.

  • Помимо аббревиатур и названий часовых поясов Postgres Pro принимает указания часовых поясов в стиле 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. Postgres Pro обрабатывает такие аббревиатуры в соответствии с их значениями на заданную дату, но, как и с примером выше EST, это не обязательно будет соответствовать местному гражданскому времени в этот день.

Независимо от формы, регистр в названиях и аббревиатурах часовых поясов не важен. (В PostgreSQL до версии 8.2 он где-то имел значение, а где-то нет.)

Ни названия, ни аббревиатуры часовых поясов, не зашиты в самом сервере; они считываются из файлов конфигурации, находящихся в путях .../share/timezone/ и .../share/timezonesets/ относительно каталога установки (см. Раздел B.4).

Параметр конфигурации TimeZone можно установить в postgresql.conf или любым другим стандартным способом, описанным в Главе 19. Часовой пояс может быть также определён следующими специальными способами:

  • Часовой пояс для текущего сеанса можно установить с помощью 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' применяется и к дню, и к часам/минутам/секундам. Postgres Pro позволяет задавать для разных компонентов разные знаки и традиционно обрабатывает знак каждого компонента в текстовом представлении отдельно от других, так что в данном случае часы/минуты/секунды будут считаться положительными. Если параметр IntervalStyle имеет значение sql_standard, ведущий знак применяется ко всем компонентам (но только если они не содержат знаки явно). В противном случае действуют традиционные правила Postgres Pro. Во избежание неоднозначности рекомендуется добавлять знак к каждому компоненту с отрицательным значением.

Значения полей могут содержать дробную часть: например, '1.5 weeks' или '01: 02: 03.45'. Однако поскольку интервал содержит только три целых единицы (месяцы, дни, микросекунды), дробные единицы должны быть разделены на более мелкие единицы. Дробные части единиц, превышающих месяцы, усекаются до целого числа месяцев, например '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: то же значение, что и выше

Тип interval представлен внутри в виде отдельных значений месяцев, дней и микросекунд. Это объясняется тем, что число дней в месяце может быть разным, а в сутках может быть и 23, и 25 часов в дни перехода на летнее/зимнее время. Значения месяцев и дней представлены целыми числами, а в микросекундах могут представляться секунды с дробной частью. Так как интервалы обычно получаются из строковых констант или при вычитании типов timestamp, этот способ хранения эффективен в большинстве случаев, но может давать неожиданные результаты:

SELECT EXTRACT(hours from '80 minutes'::interval);
 date_part
-----------
         1

SELECT EXTRACT(days from '80 hours'::interval);
 date_part
-----------
         0

Для корректировки числа дней и часов, когда они выходят за обычные границы, есть специальные функции justify_days и justify_hours.

8.5.5. Вывод интервалов

Формат вывода типа 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_standard1-23 4:05:06-1-2 +3 -4:05:06
postgres1 year 2 mons3 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_8601P1Y2MP3DT4H5M6SP-1Y-2M3DT-4H-5M-6S