S. *_*ose 2 postgresql typeorm nestjs
我尝试在主机上使用 TypeORM 和 Postgres 部署 JS 应用程序。在本地,我有一个 Postgress DB,因此在我自己的 TZ 中运行。远程主机恰好将其系统时间设置为 UTC:
$ date
Mon Oct 7 15:45:00 UTC 2019
$ psql
> select localtimestamp;
2019-10-07 15:45:00.123456
Run Code Online (Sandbox Code Playgroud)
我有一个表,其中有自动更新的日期(意味着它会在记录更新时更新)。
// my.entity.ts
@UpdateDateColumn({type: 'timestamp', name: 'lastUpdate', default: () => 'LOCALTIMESTAMP' })
lastUpdate: Date;
Run Code Online (Sandbox Code Playgroud)
一行在 12:00 CEST 插入:
> select "lastUpdate" from myTable;
2019-10-07 10:00:00.000000+00
Run Code Online (Sandbox Code Playgroud)
我想获取我的时区 (CEST) 中的日期,无论服务器时间如何,因此它应该返回我 2019-10-07 12:00。我不喜欢硬编码任何技巧,因为它也应该在我的 CEST 机器上工作。
Postgress 拥有所有信息:
> show timezone;
UCT
Run Code Online (Sandbox Code Playgroud)
所以我希望很容易将其转换为我要求的格式。但是,我发现以下示例似乎不起作用:
> 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
Run Code Online (Sandbox Code Playgroud)
有一种方法可以做到这一点,那就是指定当前时区:
> select ("lastUpdate" at time zone 'UTC' at time zone 'CEST') from myTable;
2019-10-07 12:00:00.000000
Run Code Online (Sandbox Code Playgroud)
然而,就像我说的,我不想对此进行硬编码(因为其他数据库在其他 TZ 上运行)并且 Postgres 知道它自己的时区。
还有另一种语法可以正确执行此操作吗?
无论服务器配置如何,Postgres 中的所有时间戳都以 UTC 存储。认识到这一点很重要,与其他数据库不同,它不会将您的输入解释为本地时区。但是它会将其显示回其时区。
timestamp仅存储没有时区的时间。timestamptz存储 UTC 加上时区。
在时区设置为 UTC 的 Postgres 服务器上一起演示这些内容...
=> 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
Run Code Online (Sandbox Code Playgroud)
timestamp忽略偏移量,仅存储 2019 年 10 月 7 日 10:00,无偏移量。虽然timestamptz存储 +0200 的偏移量,但以自己的 UTC 时区将时间显示给我。他们是同一时间点。
您可以将会话的数据库时区更改为 CEST。然后Postgres将在CEST中格式化timestamptz。
=> set time zone 'Antarctica/Troll';
=> select * from demo;
time | timetz
---------------------+------------------------
2019-10-07 10:00:00 | 2019-10-07 12:00:00+02
Run Code Online (Sandbox Code Playgroud)
但这很脆弱。您必须确保它在每个连接上都发生。您的应用程序依赖于数据库连接的特定配置。这是一种远距离行动反模式。格式化的内容并不明显,如果删除它,许多看似不相关的东西就会被破坏。
相反,您应该在从数据库收到时间后根据需要重新格式化时间。您可以手动执行此操作...
=> select timetz at time zone 'CEST' from demo;
timezone
---------------------
2019-10-07 12:00:00
Run Code Online (Sandbox Code Playgroud)
但通常这是您的 ORM 为您处理的事情。我不知道typeorm,但大多数都有一种一致地转换数据库类型的方法。您应该能够设置typeorm自动将 Postgres timestamptz 转换为您的本地应用程序时区。更好的是,它可以将其转换为适当的 Time 对象,而不是返回字符串,然后您可以完全控制该对象。