时区感知 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中的时区感知与时区天真

从时区偏移本地化日期时间(时区感知)

Python - 给定一个时区感知的日期时间对象,我如何获得一个时区朴素的 UTC 日期时间对象?

如何在熊猫中使用 read_csv 将时区感知日期时间作为时区天真的本地 DatetimeIndex 读取?

时区感知日期

使用 pymongo 创建时区感知 ISODate