在Hive中将本地时间转换为UTC时间

17

我在互联网上进行了大量搜索,但找不到答案。这是我的问题:

我正在Hive中编写一些查询。我有一个UTC时间戳,想将其转换为UTC时间,例如,给定时间戳1349049600,我想将其转换为UTC时间,即2012-10-01 00:00:00。然而,如果我在Hive中使用内置函数from_unixtime(1349049600),我得到的是本地PDT时间2012-09-30 17:00:00。

我意识到有一个名为from_utc_timestamp(timestamp, string timezone)的内置函数。然后我尝试像这样使用它from_utc_timestamp(1349049600, "GMT"),输出结果是1970-01-16 06:44:09.6,这完全不正确。

我不想永久更改Hive的时区,因为还有其他用户。那么,有没有办法从1349049600获取UTC时间戳字符串为“2012-10-01 00:00:00”?非常感谢!!

5个回答

19
据我所知,from_utc_timestamp()需要一个日期字符串参数,比如"2014-01-15 11:21:15",而不是一个自unix纪元以来的秒数值。这可能是当您传递一个整数时为什么它会产生奇怪的结果?唯一处理纪元秒的Hive函数似乎是from_unixtime(),它会在服务器时区中给出时间戳字符串,我在/etc/sysconfig/clock中找到了它 - 在我的情况下是"America/Montreal"。因此,您可以通过to_utc_timestamp(from_unixtime(1389802875),'America/Montreal')获得UTC时间戳字符串,然后使用from_utc_timestamp()将其转换为目标时区。这似乎非常痛苦,特别是必须将服务器TZ连接到SQL中。如果有一个from_unixtime_utc()函数或类似的东西,生活将会更加轻松。
更新: from_utc_timestamp()处理秒参数以及字符串,但随后将转换错误。当我尝试from_utc_timestamp(1389802875000, 'America/Los_Angeles')时,它给出"2014-01-15 03:21:15",这是错误的。
正确的答案是"2014-01-15 08:21:15",您可以通过以下方式(对于蒙特利尔的服务器)获得:from_utc_timestamp(to_utc_timestamp(from_unixtime(1389802875),'America/Montreal'), 'America/Los_Angeles')

1
我正在使用Hive 0.10。这看起来像是这个bug:https://issues.apache.org/jira/browse/HIVE-2867 - patricksurry

8
嘿,我只想在这里添加一点建议,我建议尝试“自动化”系统时区。因此,不要静态地设置时区。
#STATIC TZ deceleration     
to_utc_timestamp(from_unixtime(1389802875),'America/Montreal')

试试这个

#DYNAMIC TZ
select to_utc_timestamp(from_unixtime(1389802875), from_unixtime(unix_timestamp(), "z"));

这只是使用“ from_unixtime ”的字符串输出格式来返回时区字符串(小写z)


3

使用方法如下:

to_utc_timestamp(from_unixtime(timestamp),"PDT")

该函数用于将时间戳转换为PDT时区的UTC时间。

4
这个帖子得到了点赞,但似乎应该是 from_utc_timestamp(from_unixtime(timestamp),"PDT") - Chris A.
@ChrisA。用户想要将时间转换为UTC时区,这就是为什么需要这个函数。 - Akshat Singhal

1
这个例子提供了在Hive代码中硬编码系统时区TZ值的解决方案。它是在Centos环境下使用hive 0.10.0和OpenJDK Java版本1.6运行的,由于涉及时间操作,因此精确的软件版本可能很重要。目前,系统正在EDT中运行。表tblFiniteZahl类似于带有大约一百万行有限数字的DUAL表格,但可以用至少1行的任何表格替换。诀窍是在本地时区格式化时间,但使用z格式捕获时区,并在运行时提取该值以传递给to_utc_timestamp函数。
select D1,
       D1E,
       D1L,
       D1LT,
       D1LZ,
       to_utc_timestamp(D1LT, D1LZ) as D1UTC
from (
select D1,
       D1E,
       D1L,
       regexp_extract(D1L, '^([^ ]+[ ][^ ]+)[ ](.+)$', 1) as D1LT,
       regexp_extract(D1L, '^([^ ]+[ ][^ ]+)[ ](.+)$', 2) as D1LZ
from (
select D1,
       D1E,
       from_unixtime(D1E, 'yyyy-MM-dd HH:mm:ss z') as D1L
from (
select D1,
       unix_timestamp(D1,'yyyy-MM-dd HH:mm:ss Z') as D1E
from (
select '2015-08-24 01:15:23 UTC' as D1
from tblFiniteZahl
limit 1
      ) T1
      ) T2
      ) T3
      ) T4
;

结果是。
D1 = 2015-08-24 01:15:23 UTC
DT3 = 1440378923
D1L = 2015-08-23 21:15:23 EDT
D1LT = 2015-08-23 21:15:23
D1LZ = EDT
D1UTC = 2015-08-23 21:15:23

这说明to_utc_timestamp确实需要EDT作为第二个参数。

-2

我去了currentmillis.com,并粘贴了1349049600,没有意识到它实际上是秒。确实返回了1970-01-16的日期,这意味着你建议的函数:from_utc_timestamp实际上将毫秒作为第一个参数?也许你可以尝试一下from_utc_timestamp(1349049600000, "GMT")


我也尝试过,但时间仍然不对...我甚至看到一篇帖子说我们应该用1.0将1349049600000乘以(1349049600000*1.0),但还是不起作用..还是谢谢你的帮助! - Iam619
你能试一下用to_utc_timestamp吗?我认为它与语法相同。 - Sandman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接