时区感知 date_trunc 函数
Posted
技术标签:
【中文标题】时区感知 date_trunc 函数【英文标题】:timezone aware date_trunc function 【发布时间】:2014-07-25 06:10:07 【问题描述】:以下查询
SELECT the_date FROM date_trunc('day', timestamp with time zone
'2001-01-1 00:00:00+0100') as the_date
结果
the_date
2000-12-31 00:00
有没有办法告诉 date_trunc 根据输入的时区进行日/月/年转换?
预期输出为:2001-01-1 00:00+0100
【问题讨论】:
我认为你误解了timestamp with time zone
。 (这很常见,对于类型的实际语义来说,这是一个愚蠢的名称)。 timestamp with time zone
实际上不是带有时区的时间戳。它是一个存储在 UTC 中的时间戳,它在 I/O 上与客户端的 TimeZone
相互转换。
您的问题中有一个错误。您所谓的“日期”(the_date
)实际上具有timestamp
的形式,并且实际上应该是timestamptz
,因为显示的查询会返回它。我们不知道这个结果是怎么做的。此外,在不知道您当地时区的情况下,时间戳的含义是不明确的。
@ErwinBrandstetter 我同意“the_date”在这种情况下具有误导性。但是我的本地时区与这个问题有什么关系?
timestamp
值的含义取决于您在客户端中当前的时区设置。这可能会有所帮助:***.com/questions/9571392/…
【参考方案1】:
您需要指定要在哪个时区显示
select
date_trunc(
'day',
timestamp with time zone '2001-01-1 00:00:00+0100' at time zone '-02'
) as the_date;
the_date
---------------------
2001-01-01 00:00:00
AT TIME ZONE
【讨论】:
这修复了低端。但是“2001-12-31 24:00:00+0100”> 2002-01-01 00:00:00 是怎么回事? @Jay午夜是一个特例:可以从前一天被引用,但总是属于第二天。即:select timestamptz '2001-12-31 24:00:00+00'
将产生 2002-01-01 00:00:00+00
请注意,要使这个答案有意义,您的 Postgres 数据库时区需要正确设置。使用SHOW timezone;
查看其当前值,并使用例如ALTER DATABASE <db_name> SET timezone TO 'UTC';
更改其值。更多信息在这里:***.com/questions/6663765/postgres-default-timezone【参考方案2】:
虽然标记的答案对于 OP 的怪异情况可能是正确的,但对于其他人来说更可能是不正确的。您需要将 date_trunc 返回的时间戳转换为正确的时区。
select
date_trunc(
'day',
some_timestamp at time zone users_timezone
) at time zone users_timezone as the_date;
要理解的重要一点是date_trunc
返回一个timestamp
,没有附加时区。您需要将时间戳转换为正确的时区,因为数据库客户端或任何下游可能有不同的时区。
【讨论】:
【参考方案3】:@Adam 的回答肯定更有帮助。虽然我认为我们可以再次改进它,因为如果我们将时间戳截断为一天(或周/月/等),那么我们要确保我们处理的是日期对象,而不是时间戳。否则,我们可能会给其他代码片段留下这样的印象,即某些事情实际上发生发生在午夜(或可能是一天中的其他一些误导时间)。
所以我会使用:
SELECT date_trunc('day', some_timestamp AT TIME ZONE users_timezone)::date AS the_date;
将结果转换为日期,而不是时间戳。
结果会是这样的:
the_date
------------
2019-09-14
而不是更具误导性的结果:
the_date
---------------------
2019-09-14 00:00:00
【讨论】:
以上是关于时区感知 date_trunc 函数的主要内容,如果未能解决你的问题,请参考以下文章
Python - 给定一个时区感知的日期时间对象,我如何获得一个时区朴素的 UTC 日期时间对象?