Timestamptz, тот же момент времени, но другое представление для одного и того же запроса с "установить местный часовой пояс"
Я пытаюсь создать свое веб-приложение, которое будет хранить данные на сервере базы данных PostgreSQL, работающем в каком-то месте на Земле, и пользователи будут подключаться из других мест, поэтому, вероятно, часовые пояса и смещения отличаются от моих серверов.
Мне нужно показать даты и время таких действий, как, созданные сообщения, отредактированные сообщения, отправленные комментарии и т. Д. В соответствии с каждым подключенным пользователем. Это так же, как StackExchange. Однако я сталкиваюсь с проблемами часовых поясов и смещений, как описано ниже:
Кажется, все работает правильно в моем редакторе SQL pgAdmin3. Когда я пишу запрос ниже в редакторе SQL pgAdmin3 с set local time zone 'Europe/Oslo'
например, я получаю оба posts
а также tags
Таблица created_at
поля правильные с +2
смещение на выходе. В строке вывода created_at
поле posts
стол 2016-08-29 19:15:53.758+02
и для того же ряда created_at
за tags
стол 2016-08-29T19:15:53.758+02:00
,
Однако, когда я помещаю его в функцию маршрутизации на моем сервере Nodejs Express.js с pg-обещанием в качестве lib подключения, я получаю только tags
Таблица created_at
поле корректно со временем в Oslo
со смещением часового пояса, добавленным как ожидалось, я получаю created_at
поле posts
стол в UTC
не так, как ожидалось.
Все метки времени определяются как timestamp(3) with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
как показано ниже. Также без настройки set local time zone
, Я получаю то же самое поведение, для первой таблицы я получаю UTC
время, для последнего я получаю метку времени со смещением сервера.
Не set local time zone
директива связывает все запросы? В чем заключается упущение в моем подходе?
пример запроса, который я использую:
select
q.*, -- created_at timestamp (with time zone) is one of those columns
u.name as author,
u.reputation,
case when count(t.*)=0 then '[]' e 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;
Пример функции маршрута express.js:
trialRoutes.get('/x', function (req, res) {
db.query(
`
--begin;
SET LOCAL TIME ZONE 'Europe/Oslo';
SELECT
q.*, -- created_at timestamp (with time zone) is already in here
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;
--commit;
`
)
.then(function (data) {
res.json(data)
})
.catch(function (error) {
console.log("/login, database quesry error.", error);
});
})
Результат я получаю с http-сервера Express.js с pg-обещанием. Обратите внимание на различные временные метки, которые на самом деле должны указывать одну и ту же точку в UTC, что сделано правильно, и представление, которое сделано неправильно:
[
{
"id": "7",
"created_at": "2016-08-29T21:02:04.153Z", // same point in time, different representation
"title": "AAAAAAAAAAA",
"text": "aaaaa aaaaaaa aaaaaa",
"post_url": "AAAAAAAAAAA",
"score": 0,
"author_id": 1,
"parent_post_id": null,
"post_type": "question",
"is_accepted": false,
"acceptor_id": null,
"timezone": "2016-08-29T20:02:04.153Z",
"author": "Faruk",
"reputation": 0,
"tags": [
{
"id": 4,
"created_at": "2016-08-29T23:02:04.153+02:00", // same point in time, different representation
"label": "physics",
"description": null,
"category": null
}
]
},
{
"id": "6",
"created_at": "2016-08-29T17:24:10.151Z",
"title": "Ignoring timezones altogether in Rails and PostgreSQL",
"text": "Ignoring timezones altogether in Rails and PostgreSQL",
"post_url": "Ignoring-timezones-altogether-in-Rails-and-PostgreSQL",
"score": 0,
"author_id": 2,
"parent_post_id": null,
"post_type": "question",
"is_accepted": false,
"acceptor_id": null,
"timezone": "2016-08-29T16:24:10.151Z",
"author": "Selçuk",
"reputation": 0,
"tags": [
{
"id": 3,
"created_at": "2016-08-29T19:24:10.151+02:00",
"label": "sql",
"description": null,
"category": null
}
]
}
]
Определение posts
а также tags
таблицы, используемые здесь:
-- questions and answers
CREATE TABLE posts
(
id bigserial PRIMARY KEY,
created_at timestamp(3) with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
title character varying(100),
text text,
post_url character varying(100),
score integer DEFAULT 0,
author_id integer NOT NULL REFERENCES users (id),
parent_post_id integer REFERENCES posts (id),
post_type varchar(30),
is_accepted boolean DEFAULT FALSE,
acceptor_id integer REFERENCES users (id) DEFAULT NULL
--seen_by_parent_post_author boolean DEFAULT false
--view_count
--accepted_answer_id
--answer_count
);
CREATE TABLE tags
(
id bigserial PRIMARY KEY,
created_at timestamp(3) with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
label character varying(30) NOT NULL,
description character varying(200),
category character varying(50)
);