Я использую timestamp(3) with time zone
в своей базе данных для таблиц, когда это необходимо, это почти любой случай в моей ситуации.
Мне нужно выбрать все столбцы таблицы, возможно, в гораздо более сложном запросе, чем следующие.
Мой вопрос заключается в том, как получить временные метки (с часовым поясом) в нужном часовом поясе с помощью SQL at time zone '<TIMEZONE>'
для выражения выбора типа q.*
, одним из которых является столбец временной метки (с часовым поясом).
У меня могут быть подзапросы с одинаковой ситуацией.
Есть ли выражение для достижения этого для запроса?
SELECT
q.*, -- created_at timestamp (with time zone) is already in here
q.created_at AT TIME ZONE 'EET', --instead of this redundant column selection
u.name AS author,
u.reputation,
CASE WHEN count(t.*)=0 THEN '[]' ELSE json_agg(t.*) END as tags
FROM posts q
-- authors
JOIN users u
ON q.author_id = u.id
-- tags
left join post_has_tag p_h_t
on q.id = p_h_t.post_id
left join tags t
on p_h_t.tag_id = t.id
WHERE q.post_type = 'question'
group by q.id, u.id;
Ответ 1
Если ваши столбцы имеют тип timestamp
, то использование AT TIME ZONE
- это правильный способ преобразования их в определенный часовой пояс.
Однако не используйте EET
. Используйте этот часовой пояс из этого списка, например Europe/Bucharest
- или все, что применимо для вас.
В качестве альтернативы, если ваши столбцы имеют тип timestamp with time zone
, тогда вы можете установить часовой пояс сеанса, и postgres выполнит преобразование для вас:
SET TIME ZONE 'Europe/Bucharest'
Вы должны прочитать документы, чтобы понять разницу этих двух типов временных меток.
Ответ 2
Не существует волшебной установки для преобразования всех столбцов типа данных timestamptz
в timestamp
. Но вы можете установить желаемый целевой часовой пояс (временно), чтобы настроить дисплей (текстовое представление) значения timestamptz
:
BEGIN;
SET LOCAL timezone = 'EET';
SELECT q.*, -- including created_at timestamp as original timestamptz type
, u.name AS author,
, ...
-- do something with your data
COMMIT; -- or ROLLBACK; doesn't matter for just SELECT
Это не то же самое, что использовать конструкцию AT TIME ZONE
, которая фактически преобразует timestamp
в timestamptz
и наоборот. Подробности:
Эффекты SET LOCAL
продолжаются до конца транзакции.
И (например, @Matt уже упоминал), он обычно (даже если немного дороже) предпочитает использовать фактические названия часовых поясов по аббревиатурам часового пояса. Названия часовых поясов учитывают DST и другие особенности часового пояса:
SET LOCAL timezone = 'Europe/Istanbul';
Demo
BEGIN;
SET timezone = 'Europe/Istanbul';
SELECT now();
now
-----------------------------
2016-08-29 22:39:09.275647+03
SET timezone = 'UTC';
SELECT now();
now
-----------------------------
2016-08-29 19:39:09.275647+00
COMMIT;