我已经多次梳理了Google的documentation,但我似乎无法找到一个简单的函数(在SELECT
查询中)将UTC时间戳转换为不同的时区,我的案子是太平洋。对于大多数国际时区,我只需使用TIMESTAMP_SUB
或TIMESTAMP_ADD
来减去/添加偏移小时数,但美国使用夏令时会使事情变得复杂(不必要!)。
我是否遗漏了文档中的内容?或者还有其他方法可以轻松转换为另一个时区吗?
答案 0 :(得分:2)
TIMESTAMP
类型与UTC绑定。当您将TIMESTAMP
转换为与特定时区无关的其他类型时,例如STRING
,DATE
或DATETIME
,您可以指定转换的时区,例如:
SELECT EXTRACT(DATE FROM CURRENT_TIMESTAMP()
AT TIME ZONE 'America/Los_Angeles') AS current_pst_day;
如果你想要不同时区之间的(当前)小时数,你可以使用不同时区的CURRENT_DATETIME()
并采取不同的方法:
SELECT
time_zone,
DATETIME_DIFF(CURRENT_DATETIME(time_zone),
CURRENT_DATETIME(), HOUR) AS hours_from_utc
FROM UNNEST(['America/Los_Angeles', 'America/New_York']) AS time_zone;
+---------------------+----------------+
| time_zone | hours_from_utc |
+---------------------+----------------+
| America/Los_Angeles | -8 |
| America/New_York | -5 |
+---------------------+----------------+
为了使偏移更方便,您可以将其包装到SQL函数中,然后调用它以将偏移量添加到特定时间戳:
CREATE TEMP FUNCTION OffsetForTimeZone(t TIMESTAMP, time_zone STRING) AS (
TIMESTAMP_ADD(t, INTERVAL DATETIME_DIFF(CURRENT_DATETIME(time_zone),
CURRENT_DATETIME(), HOUR) HOUR)
);
SELECT OffsetForTimeZone(CURRENT_TIMESTAMP(), 'America/Los_Angeles');
请注意,此结果仍然是TIMESTAMP
与UTC相关联,尽管会被当前与太平洋时间之间的差异所抵消。
答案 1 :(得分:1)
作为Elliott答案的附录,我想测试时区数学是否适用于夏令时变化:
#standardSQL
WITH dates AS (
SELECT TIMESTAMP('2015-07-01') x, 'summer' season
UNION ALL SELECT TIMESTAMP('2015-01-01') x, 'winter' season
)
SELECT
season,
time_zone,
DATETIME_DIFF(DATETIME(x, time_zone),
DATETIME(x), HOUR) AS hours_from_utc
FROM UNNEST(['America/Los_Angeles', 'America/New_York']) AS time_zone
CROSS JOIN dates
ORDER BY 1,2
它确实:
+--------+---------------------+----------------+
| season | time_zone | hours_from_utc |
+--------+---------------------+----------------+
| summer | America/Los_Angeles | -7 |
| summer | America/New_York | -4 |
| winter | America/Los_Angeles | -8 |
| winter | America/New_York | -5 |
+--------+---------------------+----------------+
它甚至意识到智利在2015年没有通过DST:
#standardSQL
WITH dates AS (
SELECT TIMESTAMP('2014-07-01') x
UNION ALL SELECT TIMESTAMP('2015-07-01') x
UNION ALL SELECT TIMESTAMP('2016-07-01') x
)
SELECT
EXTRACT(YEAR FROM x),
time_zone,
DATETIME_DIFF(DATETIME(x, time_zone),
DATETIME(x), HOUR) AS hours_from_utc
FROM UNNEST(['Chile/Continental', 'America/New_York']) AS time_zone
CROSS JOIN dates
ORDER BY 2,2
+------+-------------------+----------------+
| f0_ | time_zone | hours_from_utc |
+------+-------------------+----------------+
| 2014 | America/New_York | -4 |
| 2015 | America/New_York | -4 |
| 2016 | America/New_York | -4 |
| 2014 | Chile/Continental | -4 |
| 2015 | Chile/Continental | -3 |
| 2016 | Chile/Continental | -4 |
+------+-------------------+----------------+
答案 2 :(得分:0)
由于最初发布我的问题,我只是使用带有偏移的TIMESTAMP_SUB
函数将默认的UTC时间戳转换为我想要的时区;我之前没有使用Elliot优雅的解决方案,因为它要求我创建一个Tableau的自定义SQL功能不允许的功能。
对于任何有兴趣的人,我现在已经找到了另一种解决方案,尽管它很丑陋。当从一种格式转换为另一种格式时,BigQuery允许内置时区偏移(例如,“America / Los_Angeles”)。例如,从timestamp到datetime:
SELECT DATETIME(CURRENT_TIMESTAMP(),"America/Los_Angeles")
示例从当前UTC时间到太平洋时间。但是,它现在采用日期时间格式,Tableau无法将其识别为日期/时间对象。为了使其恢复为时间戳格式,我将上面的函数包含在TIMESTAMP
函数中:
SELECT TIMESTAMP(DATETIME(CURRENT_TIMESTAMP(),"America/Los_Angeles"))
愚蠢,不优雅,减慢约20%,但似乎有效。
答案 3 :(得分:0)
这应该有效:
SELECT CURRENT_DATE("America/Los_Angeles")