Как получить все одинаковые дату и время независимо от часового пояса - PullRequest
4 голосов
/ 04 февраля 2012

Как мне хранить мои «даты + время» в базе данных PostgreSQL?

Вот чего я хочу достичь:

  1. Как получить все записи, которые произошли(например) 1 января 2012 г. 00:00:00 по местному времени в любой точке мира?
  2. Показать все записи, отсортированные по дате в соответствии с временем UTC.(Новый год 2012 в Нью-Йорке более поздний, чем Новый год в Лондоне).

Как хранить мои данные?Я читал, что PostgreSQL хранит все время в UTC внутри ( Документация PostgreSQL ), поэтому часовой пояс моих пользователей фактически потерян.

Я думаю, что я должен использовать один столбец с типом "timestamp без часового пояса"":

  • Точка 1 проста.
  • И с другим столбцом типа" String "я буду хранить строку часового пояса (например, America / New_York), но затем точка 2 кажетсявсе еще трудно сделать ....

Я надеюсь, что я ясен.

Редактировать новую идею: я думаю с сохранением двух временных меток: одна без часового пояса (1. хорошо) и однас часовым поясом (2. хорошо)

Ответы [ 2 ]

1 голос
/ 05 февраля 2012

Да, PostgreSQL хранит все метки времени как UTC внутри.Для timestamp with time zone смещение часового пояса применяется только для настройки времени на UTC, но не сохраняется явно.

Я бы не стал хранить строку часового пояса или даже меньше часового поясасокращение (те, которые не являются точными).Позже это может потребовать дорогостоящих вычислений, потому что вы должны учитывать летнее время и другие странности международного режима времени.

Вы можете сохранить смещение часового пояса как интервал (занимает 12 байт ) или числовое количество секунд (принимает 4 байта как целое число), как я продемонстрировал в этом связанном ответе .

Или, как вы уже предлагали: сохраните локальныйотметка времени в дополнение к отметке времени UTC (занимает 8 байт ).Это облегчит ваши задачи.Рассмотрим следующую демонстрацию: *

-- DROP TABLE tbl;
CREATE TEMP TABLE tbl (id int, ts_tz timestamp with time zone, ts timestamp);
INSERT INTO tbl VALUES
 (1,'2012-1-1 00:00+01','2012-1-1 00:00+01')
,(2,'2012-1-1 00:00+02','2012-1-1 00:00+02')
,(3,'2012-1-1 00:01+03','2012-1-1 00:01+03')
,(4,'2012-1-1 00:02+04','2012-1-1 00:02+04');

Запрос на вопрос 1:

SELECT *
FROM   tbl
WHERE  ts = '2012-1-1 00:00'::timestamp;

 id |         ts_tz          |         ts
----+------------------------+---------------------
  1 | 2012-01-01 00:00:00+01 | 2012-01-01 00:00:00
  2 | 2011-12-31 23:00:00+01 | 2012-01-01 00:00:00

Запрос на вопрос 2:

SELECT *
FROM   tbl
ORDER  BY ts_tz;

 id |         ts_tz          |         ts
----+------------------------+---------------------
  4 | 2011-12-31 21:02:00+01 | 2012-01-01 00:02:00
  3 | 2011-12-31 22:01:00+01 | 2012-01-01 00:01:00
  2 | 2011-12-31 23:00:00+01 | 2012-01-01 00:00:00
  1 | 2012-01-01 00:00:00+01 | 2012-01-01 00:00:00

сложная часть с этим решением может быть введено местное время.Это легко, если все данные вводятся локально.Но это необходимо учитывать, если вы вводите данные, скажем, для Нью-Йорка в Лос-Анджелесе.Для этого используйте AT TIME ZONE конструкцию :

SELECT ('2012-1-1 00:00+00' AT TIME ZONE 'America/New_York')::timestamp
     , ('2012-1-1 00:00+00' AT TIME ZONE 'America/Los_Angeles')::timestamp

      timezone       |      timezone
---------------------+---------------------
 2011-12-31 19:00:00 | 2011-12-31 16:00:00

Обратите внимание, как я использую метку времени с часовым поясом в качестве входных данных.AT TIME ZONE дает разные результаты для отметок времени с часовым поясом или без него.

0 голосов
/ 04 февраля 2012

Полагаю, вы можете сохранить дату в виде строки и использовать ISO 8601 или RFC 2822, чтобы вы также сохраняли часовой пояс.Или же для большего количества опций сравнения сохраняйте метку времени и часовой пояс в 2 разных столбцах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...