Как получить дату от Postgres в моем часовом поясе - PullRequest
0 голосов
/ 07 октября 2019

Я пытаюсь развернуть приложение JS, используя TypeORM и Postgres на хосте. Локально у меня был Postgress DB, так что он работал в моем собственном TZ. У удаленного хоста системное время установлено на UTC:

$ date
Mon Oct 7 15:45:00 UTC 2019

$ psql
> select localtimestamp;
2019-10-07 15:45:00.123456

У меня есть таблица с автоматически обновляемой датой (это означает, что она обновляется при обновлении записи).

// my.entity.ts
@UpdateDateColumn({type: 'timestamp', name: 'lastUpdate', default: () => 'LOCALTIMESTAMP' })
lastUpdate: Date;

Строка вставлена ​​в 12:00 CEST:

> select "lastUpdate" from myTable;
2019-10-07 10:00:00.000000+00

Я хотел бы вывести дату в моем часовом поясе (CEST) независимо от времени сервера, поэтому он должен вернуть мне 2019-10-07 12:00. Я предпочитаю не кодировать никакие трюки, потому что он также должен работать на моей машине CEST.

Postgress содержит всю информацию:

> show timezone;
UCT
  • он знает, что работает по времени UTC
  • Я могу сказать, в каком часовом поясе мне нужна дата

Так что я ожидаю, что будет легко преобразовать это в мой запрошенный формат. Тем не менее, следующие примеры, которые я обнаружил, не работают:

> select ("lastUpdate" at time zone 'CEST') from myTable;
2019-10-07 08:00:00.000000+00

> select timezone('CEST', "lastUpdate") from myTable;
2019-10-07 08:00:00.000000+00

Существует один способ сделать все правильно, указав текущий часовой пояс:

> select ("lastUpdate" at time zone 'UTC' at time zone 'CEST') from myTable;
2019-10-07 12:00:00.000000

Однако, как я уже сказал, я не хочу жестко кодировать это (как другие БД работают на других TZ), и Postgres знает, что это его собственный часовой пояс.

Есть ли другой синтаксис для правильной работы?

Ответы [ 3 ]

2 голосов
/ 07 октября 2019

Все метки времени в Postgres хранятся в UTC независимо от конфигурации сервера. Это важно понимать, в отличие от других баз данных, он не интерпретирует ваш ввод как местный часовой пояс. Однако он представит его обратно в своем часовом поясе.

timestamp хранит только время без часового пояса. timestamp хранит UTC плюс часовой пояс.

Демонстрация их вместе на сервере Postgres с его часовым поясом UTC ...

=> create table demo ( time timestamp, timetz timestamptz );
CREATE TABLE

=> insert into demo values ('2019-10-07 10:00', '2019-10-07 12:00 +0200');
INSERT 0 1

=> select * from demo;
        time         |         timetz         
---------------------+------------------------
 2019-10-07 10:00:00 | 2019-10-07 10:00:00+00

timestamp игнорирует смещение и простомагазины 7 октября 2019 года 10:00 без смещения. В то время как timestamptz хранит смещение +0200, но представляет мне время в своем часовом поясе UTC. Это один и тот же момент времени.


Вы можете изменить часовой пояс базы данных для вашего сеанса на CEST. Затем Postgres отформатирует timestamptz в CEST.

=> set time zone 'Antarctica/Troll';

=> select * from demo;
        time         |         timetz         
---------------------+------------------------
 2019-10-07 10:00:00 | 2019-10-07 12:00:00+02

Но это хрупко. Вы должны убедиться, что это происходит при каждом соединении. Ваше приложение полагается на конкретную конфигурацию подключения к вашей базе данных. Это анти-паттерн действия на расстоянии . Непонятно, что делает форматирование, и если оно удалено, многие, казалось бы, несвязанные вещи ломаются.

Вместо этого вам следует переформатировать время, как вам нравится, после получения их из базы данных. Вы можете сделать это вручную ...

=> select timetz at time zone 'CEST' from demo;
      timezone       
---------------------
 2019-10-07 12:00:00

Но, как правило, об этом заботится ORM. Я не знаю typeorm, но у большинства есть средства для последовательного перевода типов баз данных. Вы должны быть в состоянии настроить typeorm для автоматического перевода Postgres timestamptz в часовой пояс вашего локального приложения. А еще лучше, вместо того, чтобы возвращать строку, она может преобразовать ее в надлежащий объект Time, над которым вы затем имеете полный контроль.

0 голосов
/ 07 октября 2019

выберите ts_tz AT TIME ZONE 'UTC' из теста;

0 голосов
/ 07 октября 2019

выберите созданный_ател в часовом поясе 'utc' в часовом поясе 'америка / лос_анжелес' из пользователей;

...