【问题标题】:Cast fixed date into multiple time zones将固定日期投射到多个时区
【发布时间】:2019-11-13 05:31:41
【问题描述】:

我有一个固定日期(比如'2019-10-01'),我想根据time_zone 列中的值将其转换为多个时区,如下所示:

values (1, 'Asia/Jakarta'), (2, 'Asia/Manila')
-- 1 Asia/Jakarta
-- 2 Asia/Manila

当然可以存储具有每行时区的列:

values (timestamp '2019-10-01' at time zone 'Asia/Jakarta')
union all
values (timestamp '2019-10-01' at time zone 'Asia/Manila')
-- 2019-10-01 07:00:00.000 Asia/Jakarta
-- 2019-10-01 08:00:00.000 Asia/Manila

但我看不出有什么方法可以有效地完成这项工作。

datetime help page 我看到了两条途径:

  1. 使用AT TIME ZONE 不起作用 - 需要字符串文字,不是列:
select timestamp '2019-10-01' AT TIME ZONE tz
from (values ('Asia/Jakarta'), ('Asia/Manila')) t(tz)
-- line 1:44: no viable alternative at input 'TIME ZONE tz'
  1. 使用 from_unixtime 不起作用 - 只能从 unix 时间开始工作,但这是针对当前问题的 Catch 22 - 获得正确的 UTC 时间正是我们的目标。

我还缺少其他方法吗?

【问题讨论】:

    标签: presto


    【解决方案1】:

    只需使用at_timezone,它是AT TIME ZONE <literal> 的动态等效项。

    presto:default> SELECT id, at_timezone(CAST('2019-10-01' AS date), tz)
                 -> FROM (VALUES (1, 'Asia/Jakarta'), (2, 'Asia/Manila')) t(id, tz);
     id |                _col1
    ----+--------------------------------------
      1 | 2019-10-01 05:00:00.000 Asia/Jakarta
      2 | 2019-10-01 06:00:00.000 Asia/Manila
    (2 rows)
    

    相关:要将一个分区日期时间更改为不同的区域(同时保留时间点),您可以使用 with_timezone。因此,请确保 at_timezone 为您提供所需的语义。

    (在 Presto 324 上测试)

    【讨论】:

    • 似乎还有一个 Hive 函数可用:to_utc_timestamp 接受 tz 参数
    【解决方案2】:

    这是一个非常尴尬的方法;我希望有更好的东西(特别是,它对时区偏移量随时间变化并不稳健,例如夏令时):

    select
        from_iso8601_timestamp(concat('2019-10-01', 'T00:00:00.000+', h, ':', m)) t
    from (
      select 
          -- a bit hackier: use regexp_extract(to_iso8601(ts), '[+].*'),
          --   which also allows you to un-nest this part of the query
          lpad(cast(timezone_hour(ts) as varchar), 2, '0') h, 
          lpad(cast(timezone_minute(ts) as varchar), 2, '0') m
      from (
        -- easier to write 0, BUT, this is more robust to change
        --   of timezone definitions since 1970 (relatively common)
        select from_unixtime(to_unixtime(current_timestamp), tz) ts
        from ( values ('Asia/Jakarta'), ('Asia/Manila')) t(tz)
      )
    )
    -- 2019-10-01 00:00:00.000 +07:00
    -- 2019-10-01 00:00:00.000 +08:00
    

    鉴于缺乏稳健性,也应该有一个大致等效的方法,使用 difftime

    【讨论】:

      猜你喜欢
      • 2019-01-26
      • 2014-06-16
      • 1970-01-01
      • 2012-04-13
      • 2011-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-30
      相关资源
      最近更新 更多