【问题标题】:timezone aware date_trunc function时区感知 date_trunc 函数
【发布时间】: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 值的含义取决于您在客户端中当前的时区设置。这可能会有所帮助:stackoverflow.com/questions/9571392/…

标签: postgresql timezone timezone-offset


【解决方案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'; 更改其值。更多信息在这里:stackoverflow.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
    

    【讨论】:

      猜你喜欢
      • 2013-07-08
      • 2019-01-18
      • 2016-05-07
      • 1970-01-01
      • 2013-11-15
      • 2012-04-17
      • 1970-01-01
      • 1970-01-01
      • 2019-01-02
      相关资源
      最近更新 更多