Lar*_*nal 165 postgresql timezone types
存储时间戳值不同PostgreSQL中,当数据类型是WITH TIME ZONE
对WITHOUT TIME ZONE
?可以用简单的测试用例说明差异吗?
big*_*ose 141
PostgreSQL文档中介绍了日期/时间类型的差异.是的,一个或多个的处理TIME
或TIMESTAMP
不同.它不会影响值的存储方式; 它会影响它们的解释方式.WITH TIME ZONE
WITHOUT TIME ZONE
这些数据类型的时区的影响被明确包括在文档.不同之处在于系统可以合理地了解价值:
使用时区作为值的一部分,可以将值呈现为客户端中的本地时间.
如果没有时区作为值的一部分,则明显的默认时区是UTC,因此将为该时区进行渲染.
行为的不同取决于至少三个因素:
WITH TIME ZONE
或WITHOUT TIME ZONE
).以下是涵盖这些因素组合的示例:
foo=> SET TIMEZONE TO 'Japan';
SET
foo=> SELECT '2011-01-01 00:00:00'::TIMESTAMP;
timestamp
---------------------
2011-01-01 00:00:00
(1 row)
foo=> SELECT '2011-01-01 00:00:00'::TIMESTAMP WITH TIME ZONE;
timestamptz
------------------------
2011-01-01 00:00:00+09
(1 row)
foo=> SELECT '2011-01-01 00:00:00+03'::TIMESTAMP;
timestamp
---------------------
2011-01-01 00:00:00
(1 row)
foo=> SELECT '2011-01-01 00:00:00+03'::TIMESTAMP WITH TIME ZONE;
timestamptz
------------------------
2011-01-01 06:00:00+09
(1 row)
foo=> SET TIMEZONE TO 'Australia/Melbourne';
SET
foo=> SELECT '2011-01-01 00:00:00'::TIMESTAMP;
timestamp
---------------------
2011-01-01 00:00:00
(1 row)
foo=> SELECT '2011-01-01 00:00:00'::TIMESTAMP WITH TIME ZONE;
timestamptz
------------------------
2011-01-01 00:00:00+11
(1 row)
foo=> SELECT '2011-01-01 00:00:00+03'::TIMESTAMP;
timestamp
---------------------
2011-01-01 00:00:00
(1 row)
foo=> SELECT '2011-01-01 00:00:00+03'::TIMESTAMP WITH TIME ZONE;
timestamptz
------------------------
2011-01-01 08:00:00+11
(1 row)
Run Code Online (Sandbox Code Playgroud)
dde*_*any 22
我试着解释它比引用的PostgreSQL文档更容易理解.
TIMESTAMP
尽管名称暗示,这两种变体都不存储时区(或偏移量).不同之处在于对存储数据(以及预期应用程序)的解释,而不是存储格式本身:
TIMESTAMP WITHOUT TIME ZONE
存储本地日期时间(又名.挂历日期和挂钟时间).就PostgreSQL而言,它的时区是未指定的(尽管你的应用程序可能知道它是什么).因此,PostgreSQL在输入或输出上没有时区相关的转换.如果将值输入到数据库中'2011-07-01 06:30:30'
,那么在以后显示的时区中没有任何内容,它仍然会显示2011年,07月,第01天,06小时,30分钟和30秒(以某种格式).此外,任何偏移或者您在输入指定的时区是PostgreSQL可以忽略,所以'2011-07-01 06:30:30+00'
和'2011-07-01 06:30:30+05'
如一样的'2011-07-01 06:30:30'
.对于Java开发人员:它类似于java.time.LocalDateTime
.
TIMESTAMP WITH TIME ZONE
在UTC时间线上存储一个点.它的外观(多少小时,分钟等)取决于你的时区,但它总是指同一个"物理"瞬间(就像实际物理事件的那一刻).输入内部转换为UTC,这就是它的存储方式.为此,必须知道输入的偏移量,因此当输入不包含显式偏移量或时区(如'2011-07-01 06:30:30'
)时,假定它位于PostgreSQL会话的当前时区,否则使用显式指定的偏移量或时区(如'2011-07-01 06:30:30+05'
).输出显示转换为PostgreSQL会话的当前时区.对于Java开发人员:它类似于java.time.Instant
(尽管与分辨率较低),但与JDBC和JPA 2.2你应该把它映射到java.time.OffsetDateTime
(或java.util.Date
或java.sql.Timestamp
课程).
有人说这两种TIMESTAMP
变化都存储了UTC日期时间.有点,但在我看来这样说是令人困惑的.TIMESTAMP WITHOUT TIME ZONE
存储方式类似于a TIMESTAMP WITH TIME ZONE
,使用UTC时区进行渲染时,会产生与本地日期时间相同的年,月,日,小时,分钟,秒和微秒.但这并不意味着代表UTC解释所说的时间线上的点,它只是本地日期时间字段编码的方式.(它是时间线上的一些点簇,因为实时区域不是UTC;我们不知道它是什么.)
小智 12
PostgreSQL 官方文档中显示了差异。请参阅文档进行深入挖掘。
简而言之,TIMESTAMP WITHOUT TIME ZONE
如果您提供带有时区信息的日期时间,则不会保存任何时区相关信息,它仅需要日期和时间并忽略时区
例如
当我将其保存12:13, 11 June 2021 IST
到 PostgreSQL时TIMESTAMP WITHOUT TIME ZONE
,将拒绝时区信息并保存日期时间12:13,11 June 2021
但它的情况是以格式TIMESTAMP WITH TIME ZONE
保存时区信息的UTC
。
例如
当我将其保存12:13, 11 June 2021 IST
到 PostgreSQLTIMESTAMP WITH TIME ZONE
类型变量时,它将将此时间解释为UTC
值并存储,如下所示6:43,11 June 2021 UTC
注意:UTC + 5.30 为 IST
在时间转换期间,返回的时间TIMESTAMP WITH TIME ZONE
将以 UTC 格式存储,我们可以将其转换为所需的时区,如 IST 或 PST 等。
所以PostgreSQL中推荐的时间戳类型是TIMESTAMP WITH TIME ZONE
或者 TIMESTAMPZ
ser*_*rby 10
这是一个应该有用的例子.如果您有带时区的时间戳,则可以将该时间戳转换为任何其他时区.如果您没有基准时区,则无法正确转换.
SELECT now(),
now()::timestamp,
now() AT TIME ZONE 'CST',
now()::timestamp AT TIME ZONE 'CST'
Run Code Online (Sandbox Code Playgroud)
输出:
-[ RECORD 1 ]---------------------------
now | 2018-09-15 17:01:36.399357+03
now | 2018-09-15 17:01:36.399357
timezone | 2018-09-15 08:01:36.399357
timezone | 2018-09-16 02:01:36.399357+03
Run Code Online (Sandbox Code Playgroud)
时间戳与时间戳
Postgres 中的 timestamptz 字段基本上只是 Postgres 实际上只存储“标准化”UTC 时间的时间戳字段,即使输入字符串中给出的时间戳具有时区。
如果你的输入字符串是: 2018-08-28T12:30:00+05:30 ,当这个时间戳存储在数据库中时,它会存储为 2018-08-28T07:00:00 。
与简单的时间戳字段相比,这样做的优势在于您对数据库的输入将与时区无关,并且当来自不同时区的应用程序插入时间戳时,或者当您将数据库服务器位置移动到不同的时区时,不会不准确。
引用文档:
对于带时区的时间戳,内部存储的值始终采用 UTC(世界协调时间,传统上称为格林威治标准时间,GMT)。使用该时区的适当偏移量将具有指定显式时区的输入值转换为 UTC。如果输入字符串中未指定时区,则假定它位于系统的 TimeZone 参数指示的时区中,并使用时区区域的偏移量转换为 UTC。做一个简单的类比,timestamptz 值代表一个时刻,对于任何查看它的人来说都是同一时刻。但是时间戳值仅代表时钟的特定方向,它将代表基于您的时区的不同时间实例。
对于几乎所有用例,timestamptz 几乎总是更好的选择。由于timestamptz 和timestamp 占用相同的8 个字节的数据,这一选择变得更加容易。
来源:https : //hasura.io/blog/postgres-date-time-data-types-on-graphql-fd926e86ee87/
归档时间: |
|
查看次数: |
175408 次 |
最近记录: |