我有一个固定的日期(例如'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中,我看到了两种途径:
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'
from_unixtime
不起作用-仅从Unix时间开始起作用,但这是当前问题的Catch 22-准确地确定UTC时间是目标。我还缺少其他方法吗?
答案 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
大致等效。