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

PostgreSQL поддерживает полный список SQL типов даты и времени, который представлен в Table 8-9. Операции, которые доступны для этих типов данных, описываются в Section 9.9.

Table 8-9. Типы даты/времени

ИмяРазмер храненияОписаниеНаименьшее значениеНаибольшее значениеРазрешение(шаг)
timestamp [ (p) ] [ without time zone ]8 байти дата и время4713 BC5874897 AD1 микросекунда / 14 разрядов
timestamp [ (p) ] with time zone8 байти дата и время без временной зоны4713 BC5874897 AD1 микросекунда / 14 разрядов
interval [ (p) ]12 байтвремя в интервалах-178000000 лет178000000 лет1 микросекунда / 14 разрядов
date4 байтатолько даты4713 BC5874897 AD1 день
time [ (p) ] [ without time zone ]8 байттолько время00:00:0024:00:001 микросекунда / 14 разрядов
time [ (p) ] with time zone12 байттолько время без временной зоны00:00:00+135924:00:00-13591 микросекунда / 14 разрядов

Note: До PostgreSQL 7.3, указание timestamp был эквивалентно типу дата и время без временной зоны. Для соответствия стандарту SQL это был изменено.

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

Note: Если значения timestamp сохраняются как число с плавающей запятой двойной точности (по умолчанию это так), то эффективное ограничение на точность может быть меньше 6. Значения timestamp хранятся как количество секунд перед или после 2000-01-01. Микросекундная точность достигается для дат, которые находятся внутри отрезка, начинающегося с 2000-01-01, но эта точность снижается для дат вне этого отрезка. Когда значения timestamp сохраняются как восьмибайтные целые числа (опция задаваемая при компиляции), то микросекундная точность становится доступной для всего диапазона значений дат. Однако, восьмибайтные целые значения timestamp имеют более ограниченный диапазон дат, как говорилось выше: от 4713 BC до 294276 AD. Та же опция во время компиляции также определяет будут ли значения time т interval храниться как числа с плавающей точкой или как восьмибайтные целые числа. В случае чисел с плавающей точкой, бОльшие значения interval имеют меньшую точность из-за увеличения размера самого интервала.

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

Тип 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, чтобы выбрать порядок следования год-месяц-день.

В PostgreSQL управление вводом значений даты и времени устроено более удобно, чем этого требует стандарт SQL. Смотрите Appendix B, чтобы узнать о точных правилах разбора вводимых значений даты/времени и о распознавании текстовых полей, включая месяцы, дни недели и временные зоны.

Помните, что любые вводимые значения даты или времени необходимо заключать в одиночные кавычки, как и текстовые строки. Больше информации можно найти в Section 4.1.2.5. SQL требует следующего синтаксиса

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

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

8.5.1.1. Даты

Table 8-10 показывает некоторые возможные формы ввода для типа date.

Table 8-10. Ввод значений даты

ПримерОписание
January 8, 1999значение является однозначным для любого datestyle режима ввода
1999-01-08ISO 8601; 8 января в любом режиме (рекомендуемый формат)
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.

Правильные вводимые значения для этих типов состоят из времени дня, за которым следует необязательное значение временной зоны. (См. Table 8-11 и Table 8-12.) Если временная зона задаётся при вводе значений типа time without time zone, то она молча игнорируется. Вы также всегда можете задать дату, но она будет проигнорирована, за исключением случая, когда вы используете полное имя временной зоны, как например America/New_York. В этом случае дата задаётся принудительно, чтобы понять какое смещение временной зоны нужно применять. Оно будет применено, если при вводе было указано любое допустимое смещение временной зоны, при условии, что дата и время находятся в положенном месте вводимого значения.

Table 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
04:05:06-08:00ISO 8601
04:05-08:00ISO 8601
040506-08ISO 8601
04:05:06 PSTвременная зона, заданная именем
2003-04-12 04:05:06 America/New_Yorkвременная зона, заданная полным именем

Table 8-12. Ввод значений временной зоны

ПримерОписание
PSTPacific Standard Time
America/New_YorkПолное имя временной зоны
-8:00ISO-8601 смещение для PST
-800ISO-8601 смещение для PST
-8ISO-8601 смещение для PST
zuluВоенная аббревиатура для UTC
zКраткая форма zulu

Список имён временных зон, которые распознаются при вводе смотрите вo Appendix B.

8.5.1.3. Дата и время

Правильные вводимые значения для типа даты и времени состоят из слитного значения даты и времени, за которым следует необязательное значение временной зоны, за которым следует необязательный суффикс AD или BC. (В качестве альтернативы, AD/BC могут указываться перед временной зоной, но так делать не рекомендуется.) Таким образом

1999-01-08 04:05:06

и

1999-01-08 04:05:06 -8:00

являются правильными значениями, которые соответствуют стандарту ISO 8601. В дополнение, поддерживается расширенный формат стандарта. Вы также можете задать полное имя временной зоны:

1999-01-08 04:05:06 America/New_York

В дополнение, расширенный формат:

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 timezone, PostgreSQL будет молча игнорировать любые указания временной зоны. Таким образом, итоговое значение будет получено из полей даты/времени, которые присутствуют во вводимом значении и не будет скорректировано по временной зоне.

Для типа timestamp with time zone, значение внутри, всегда хранится в UTC (Universal Coordinated Time, обычно известное как время Гринвичского (нулевого) меридиана или GMT). Вводимое значение, которое имеет явно заданную временную зону, конвертируется в UTC, используя смещение, соответствующее этой временной зоне. Если при вводе временная зона не указана, то временная зона берётся из системного параметра timezone и точно также конвертируется в UTC, используя смещение временной зоны, указанной в переменной timezone.

Когда выводится значение типа timestamp with time zone, оно всегда конвертируется из UTC во временную зону, заданную переменной timezone и отображается как местное время в этой зоне. Чтобы увидеть это же время в другой временной зоне, или измените значение переменной timezone или используйте конструкцию AT TIME ZONE (см. Section 9.9.3).

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

8.5.1.4. Интервалы

Значения типа interval могут записываться по следующему синтаксису:

[@] количество элемент [количество элемент...] [направление]

Где: количество ‐ это количество (возможно со знаком); элементов, которые могут иметь значение second(секунда), minute(минута), hour(час), day(день), week(неделя), month(месяц), year(год), decade(декада), century(век), millennium(тысячелетие), или аббревиатуру или множество этих элементов; направление может иметь значения ago(назад) или пусто. Знак (@) не обязательно важен. Итоговые значения разных элементов неявно дополняются соответствующим знаком.

Количество дней, часов, минут и секунд может быть задано без явного указания элементов. Например, значение '1 12:59:10' будет распознано также как и значение '1 день 12 часов 59 минут 10 секунд'.

Необязательное значение точности p должно быть в интевале от 0 до 6, и используется как значение точности по умолчанию для вводимых значений.

Внутренние значения типа interval хранятся как месяцы, дни и секунды. Это сделано потому что количество дней в месяце меняется и день может иметь 23 или 25 часов, если выполняется переход на летнее и зимнее время. Поскольку интервалы обычно создаются из строковых констант или разности значений timestamp, то данный метод хранения прекрасно работает в большинстве случаев. Функции justify_days и justify_hours доступны для корректировки дней и часов, которые выходят за пределы их нормальных периодов.

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

PostgreSQL поддерживает для удобства несколько специальных значений ввода даты/времени, как показано в Table 8-13. Из этих значений infinity и -infinity специально представлены внутри СУБД и будут показываться в таком же виде; но другие являются просто сокращениями, которые будут преобразованы при вводе в обычные значения даты/времени. (Например, now и подобные строки преобразоываются в определённое значение времени в момент, когда их читает СУБД.) Все такие значения, когда они используется в командах SQL, должны записываться в одинарных кавычках.

Table 8-13. Специальные значения даты/времени

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

Также получить текущее значение времени для соответствующих типов данных можно используя следующие, совместимые со стандартом SQL функции: CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP, LOCALTIME, LOCALTIMESTAMP. Последние четыре функции позволяют задать необязательную точность. (См. Section 9.9.4.) Заметим однако, что это функции SQL и что они не рапознаются как строки данных.

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

Формат вывода значений типов даты/времени может быть установлен в одном из четырёх стилей: ISO 8601, SQL (Ingres), традиционный POSTGRES и German, с помощью команды SET datestyle. По умолчанию устанавливается формат ISO. (Стандарт SQL требует использования формата ISO 8601. Название формата вывода "SQL" является исторически сложившимся.) Table 8-14 показывает примеры каждого стиля вывода. Вывод значений типов date и time, разумеется, только часть даты и времени в соответствии с данными примерами.

Table 8-14. Стили вывода даты/времени

Спецификация стиляОписаниеПример
ISOстандарт ISO 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

В стилях SQL и POSTGRES, день идёт перед месяцем, если быд задан порядок полей DMY, в противном случае месяц следует перед днём. (См. Section 8.5.1 о том как эта настройка также отказывает эффект на интерпретацию вводимых значений.) В Table 8-15 показан пример.

Table 8-15. Соглашения по датам

Установка стиля датыВходимое значениеПример вывода
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

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

[ quantity unit [ ... ] ] [ days ] [ hours:minutes:seconds ]

Пользователь может выбрать нужные ему стили даты/времени с помощью команды SET datestyle, параметра DateStyle в конфигурационном файле postgresql.conf или с установив переменную окружения PGDATESTYLE на сервере или клиенте. Функция форматирования to_char (см. Section 9.8) также может быть использована как более гибкий способ форматирования выводимых значений даты/времени.

8.5.3. Временные зоны

Временные зоны и соглашения по временным зонам зависят не только геометрии планеты, но и от политического территориального деления. Временные зоны во всём мире стали чем-то стандартным, начиная с 1900 года, но продолжают соответствующим образом изменяться, учитывая правила летнего/зимнего времени. В настоящий момент PostgreSQL поддерживает правила перехода на летнее/зимнее время в периоде с 1902 по 2038 годы (соответствующие полному диапазону системного времени Unix). Время за пределами этого диапазона считается "стандартным временем" для выбранной временной зоны, не учитывая, что оно может быть неправильным для части года.

PostgreSQL прикладывает усилия для совместимости со стандартом SQL при работе с типовыми операциями. Однако, в стандарте SQL есть разнородная смесь типов даты и времени, а также совместимых с ними типов. Вот две очевидные проблемы:

Из-за этих трудностей, мы рекомендуем при использовании временных зон использовать типы даты/времени, которые содержат как дату, так и время. Мы не рекомендуем использовать тип time with time zone (хотя он поддерживается PostgreSQL для старых приложений и для совместимости со стандартом SQL). PostgreSQL для всех типов, которые содержат только дату или только время использует вашу локальную временную зону.

Все даты, учитывающие временную зону и время хранятся внутри в UTC. Перед тем как значения будут выданы клиенту, они преобразуются в локальное время в соответствии с настройками, указанными в параметре timezone.

Параметр timezone может быть установлен в файле postgresql.conf или любым другим стандартным способом, описанным в Chapter 17. Также существует несколько специальных способов его установки:

Список доступных временных зон смотрите в Appendix B.

8.5.4. Некоторые подробности по датам

PostgreSQL использует для всех вычислений даты/времени Юлианский календарь. У него есть прекрасное свойство предсказывать/вычислять любую дату, которая следует за годом 4713 до н.э., потому что используется длина года, равная 365.2425 дням.

Соглашения по датам, которые использовались до 19-го века интересны, но не позволяют целостно использовать их при кодировании обработки даты/времени.