作为ETL到Redshift的一部分,在源表之一中,有2列:
original_timestamp - TIMESTAMP
:这是在任何区域插入记录的本地时间
original_timezone_offset - Varchar
:这是UTC的偏移量
数据看起来像这样:
original_timestamp original_timezone_offset 2011-06-22 11:00:00.000000 -0700 2014-11-29 17:00:00.000000 -0800 2014-12-02 22:00:00.000000 +0900 2011-06-03 09:23:00.000000 -0700 2011-07-28 03:00:00.000000 -0700 2011-05-01 01:30:00.000000 -0700
在目标表中,我需要将其转换为UTC(使用偏移量)。我该怎么做?
到目前为止,我已经尝试了多种方法,但是dateadd()
似乎是最接近的解决方案。但是dateadd()
的问题是,当我说:
SELECT original_timestamp, original_timezone_offset
,dateadd(H, original_timezone_offset, original_timestamp) as original_utc_time
由于偏移量是VARCHAR,并且值类似:-0700
等,因此它会将原始时间戳添加/减去“ 700” /“ 800”小时,而不是原始时间戳的7/8小时。
有人以前见过这个问题吗?感谢任何帮助/输入。谢谢。
答案 0 :(得分:0)
首先,请认识到,如果您的时间戳已经在给定偏移量的本地时间中,那么您需要减去该偏移量以转换回UTC。在您给出的第一个示例中,2011-06-22 11:00:00 -0700
等效于2011-06-22 18:00:00 UTC
。
但是,应该让AT TIME ZONE
函数为您完成工作,而不是自己尝试添加或减去这些值。它将创建一个timestamptz
,位于您提供的偏移量中,然后您可以再次使用它来转换为UTC。
(请注意,您可以改用CONVERT_TIMEZONE
函数,但是Redshift只能理解该函数,其中AT TIME ZONE
也可以在常规PostgreSQL上运行。)
但是,您所拥有的时区偏移不是这些函数可以理解的格式。参见time zone usage notes。因此,在尝试转换之前,让我们将偏移量字符串转换为可以理解的格式。
我们希望-0700
成为+07:00
。冒号是必需的,并且必须翻转符号,因为它将以POSIX样式的时区格式解释。以这种格式,正值位于GMT的 west 处,而不是ISO 8601中指定的常规约定。
concat(translate(substring(original_timezone_offset, 1, 3), '-+', '+-'),':',substring(original_timezone_offset, 4, 2))
然后,我们将其与AT TIME ZONE
一起使用来进行转换:
(original_timezone AT TIME ZONE <the above mess>) AT TIME ZONE 'UTC' AS utc_timestamp
将它们放在一起...
WITH t as (
SELECT '2011-06-22 11:00:00.000000'::timestamp as original_timestamp, '-0700' as original_timezone_offset
UNION ALL
SELECT '2014-11-29 17:00:00.000000'::timestamp,'-0800'
UNION ALL
SELECT '2014-12-02 22:00:00.000000'::timestamp,'+0900'
)
SELECT
original_timestamp,
original_timezone_offset,
concat(translate(substring(original_timezone_offset, 1, 3), '-+', '+-'),':',substring(original_timezone_offset, 4, 2)) as modified_timezone_offset,
(original_timestamp AT TIME ZONE concat(translate(substring(original_timezone_offset, 1, 3), '-+', '+-'),':',substring(original_timezone_offset, 4, 2))) AT TIME ZONE 'UTC' AS utc_timestamptz
FROM t
输出:
2011-06-22 11:00:00 -0700 +07:00 2011-06-22 18:00:00
2014-11-29 17:00:00 -0800 +08:00 2014-11-30 01:00:00
2014-12-02 22:00:00 +0900 -09:00 2014-12-02 13:00:00