将固定日期投放到多个时区

时间:2019-11-12 10:24:41

标签: presto

我有一个固定的日期(例如'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时间是目标。

我还缺少其他方法吗?

2 个答案:

答案 0 :(得分:2)

只需使用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上测试)

答案 1 :(得分:0)

这是一个非常尴尬的方法;我希望有更好的方法(尤其是时区偏移量随时间变化(例如用于夏时制)并不可靠):

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大致等效。