4 ответов:
различия рассматриваются в документация PostgreSQL для типов даты/времени. Да, лечение
TIMEилиTIMESTAMPотличается междуWITH TIME ZONEилиWITHOUT TIME ZONE. Это не влияет на то, как хранятся значения; это влияет на то, как они интерпретируются.влияние часовых поясов на эти типы данных является в нем конкретно в документации. Разница возникает из того, что система может разумно знать о значение:
с часовым поясом в качестве части значения, значение может быть отображено как местное время в клиенте.
без часового пояса в качестве части значения очевидным часовым поясом по умолчанию является UTC, поэтому он отображается для этого часового пояса.
поведение зависит от трех факторов:
- настройка часового пояса в клиенте.
- тип данных (т. е.
WITH TIME ZONEилиWITHOUT TIME ZONE) значения.- указано ли значение с определенным часовым поясом.
вот примеры, охватывающие комбинации этих факторов:
foo=> SET TIMEZONE TO 'Japan'; SET foo=> SELECT '2011-01-01 00:00:00'::TIMESTAMP; timestamp --------------------- 2011-01-01 00:00:00 (1 row) foo=> SELECT '2011-01-01 00:00:00'::TIMESTAMP WITH TIME ZONE; timestamptz ------------------------ 2011-01-01 00:00:00+09 (1 row) foo=> SELECT '2011-01-01 00:00:00+03'::TIMESTAMP; timestamp --------------------- 2011-01-01 00:00:00 (1 row) foo=> SELECT '2011-01-01 00:00:00+03'::TIMESTAMP WITH TIME ZONE; timestamptz ------------------------ 2011-01-01 06:00:00+09 (1 row) foo=> SET TIMEZONE TO 'Australia/Melbourne'; SET foo=> SELECT '2011-01-01 00:00:00'::TIMESTAMP; timestamp --------------------- 2011-01-01 00:00:00 (1 row) foo=> SELECT '2011-01-01 00:00:00'::TIMESTAMP WITH TIME ZONE; timestamptz ------------------------ 2011-01-01 00:00:00+11 (1 row) foo=> SELECT '2011-01-01 00:00:00+03'::TIMESTAMP; timestamp --------------------- 2011-01-01 00:00:00 (1 row) foo=> SELECT '2011-01-01 00:00:00+03'::TIMESTAMP WITH TIME ZONE; timestamptz ------------------------ 2011-01-01 08:00:00+11 (1 row)
я пытаюсь объяснить это более понятно, чем упомянутая документация PostgreSQL.
ни
TIMESTAMPварианты хранят часовой пояс (или смещение), несмотря на то, что предлагают имена. Разница заключается в интерпретации сохраненных данных (и в предполагаемом приложении), а не в самом формате хранения:
TIMESTAMP WITHOUT TIME ZONEмагазинах local дата-время (ака. настенный календарь дата и настенные часы время). Часовой пояс не указан насколько PostgreSQL может сказать (хотя ваше приложение может знать, что это такое). Следовательно, PostgreSQL не выполняет преобразование, связанное с часовым поясом, на входе или выходе. Если значение было введено в базу данных как'2011-07-01 06:30:30', то независимо от того, в каком часовом поясе вы отображаете его позже, он все равно будет говорить Год 2011, месяц 07, день 01, 06 часов, 30 минут и 30 секунд (в некотором формате). Кроме того, любое смещение или часовой пояс, указанный во входных данных, игнорируется PostgreSQL, поэтому'2011-07-01 06:30:30+00'и'2011-07-01 06:30:30+05'такие же, как и просто'2011-07-01 06:30:30'. Для разработчиков Java: это аналогичноjava.time.LocalDateTime.
TIMESTAMP WITH TIME ZONEсохраняет точку на линии времени UTC. Как он выглядит (сколько часов, минут и т. д.) зависит от вашего часового пояса, но он всегда относится к одному и тому же "физическому" моменту (например, момент фактического физического события). Этот ввод внутренне преобразуется в UTC, и именно так он хранится. Для этого необходимо знать смещение входа, поэтому, когда вход не содержит явного смещения или часового пояса (например'2011-07-01 06:30:30') предполагается, что он находится в текущем часовом поясе сеанса PostgreSQL, в противном случае используется явно указанное смещение или часовой пояс (как в'2011-07-01 06:30:30+05'). Вывод отображается преобразованным в текущий часовой пояс сеанса PostgreSQL. Для разработчиков Java: это аналогичноjava.time.Instant(С более низким разрешением, хотя), но с JDBC и JPA 2.2 вы должны сопоставить его сjava.time.OffsetDateTime(илиjava.util.Dateилиjava.sql.Timestampконечно).некоторые говорят, что обе
TIMESTAMPвариации хранить UTC дата-время. Отчасти, но это сбивает с толку, чтобы выразить это таким образом, на мой взгляд.TIMESTAMP WITHOUT TIME ZONEхранениеTIMESTAMP WITH TIME ZONE, который отображается с часовым поясом UTC, дает тот же год, месяц, день, часы, минуты, секунды и микросекунды, что и в локальном времени даты. Но он не предназначен для представления точки на временной линии, о которой говорит интерпретация UTC, это просто способ кодирования локальных полей даты и времени. (Это какой-то кластер точек на временной линии, как настоящий часовой пояс не UTC; мы не знаем, что это такое.)
вот пример, который должен помочь. Если у вас есть метка времени с часовым поясом, вы можете преобразовать эту метку времени в любой другой часовой пояс. Если у вас нет базового часового пояса, он не будет преобразован правильно.
SELECT now(), now()::timestamp, now() AT TIME ZONE 'CST', now()::timestamp AT TIME ZONE 'CST'выход:
-[ RECORD 1 ]--------------------------- now | 2018-09-15 17:01:36.399357+03 now | 2018-09-15 17:01:36.399357 timezone | 2018-09-15 08:01:36.399357 timezone | 2018-09-16 02:01:36.399357+03
SELECT MAX('2017-07-06 12:20:48.446+00') - MIN('2017-06-06 12:20:48.446+00') as time_to_take from table_name
Comments