【问题标题】:How can i convert a timestamp to gmt format in hive如何在 hive 中将时间戳转换为 gmt 格式
【发布时间】:2017-02-13 21:03:01
【问题描述】:

我的表中有一个时间戳列,我从时间戳列中派生出一个名为 dt_skey 的列。为了清楚地解释,我们假设时间戳列名称为time_column。这就是 time_column 看起来像 2017-02-05 03:33:50dt_skey 列看起来像 20170205033350 的样子,这只是删除了它们之间的符号。

我的问题是:time_column 位于 est 时区,我想将其转换为 gmt 格式,同时从中导出 dt_skey。我想这样做的原因是当我们通过 impala 查询时间戳时,它会被转换为 gmt 格式,因为 dt_skey 不会被转换,因为它是一个 int 数据类型。我正在通过 hive 进行摄取,当我们通过 hive 查询时,时间戳和dt_skey 列将同步。出于报告目的和我们使用 impala 的用户,所以我想对 dt_skey 列进行更改,以便如果用户查看 impala,则两个列应该是同步的。

下面是我用来从时间戳列派生dt_skey 列的 sql:

cast(substr(regexp_replace(cast(time_column as string), '-',''),1,8) as int)as dt_skey

上述查询会将这个2017-02-02 07:32:51 转换成这个20170202

请帮助我将 dt_skey 偏移为 GMT 格式。我也欢迎通过 spark 解决方案。

【问题讨论】:

  • 为什么是mysql 标签?删除破折号时,您确定“2017-02-05”变为“20170233”吗?
  • 我的 sql 标签是因为 hive 使用了很多 sql 查询,并且日期将与刚刚删除中间的破折号一样,我刚刚编辑了问题,请查看更改。谢谢你

标签: mysql hadoop apache-spark hive impala


【解决方案1】:

在 Spark 中:

rdd = spark.sparkContext.parallelize([('2017-02-05 03:33:50',)])
df = spark.createDataFrame(rdd, ['EST'])
df = df.withColumn('GMT', f.to_utc_timestamp(df['EST'], 'EST'))
res = df.withColumn('YouWanna', f.date_format(df['GMT'], 'yyyyMMddHHmmss'))
res.show(truncate=False)

+-------------------+---------------------+--------------+
|EST                |GMT                  |YouWanna      |
+-------------------+---------------------+--------------+
|2017-02-05 03:33:50|2017-02-05 08:33:50.0|20170205083350|
+-------------------+---------------------+--------------+

或者在蜂巢中:

select date_format(to_utc_timestamp('2017-02-05 03:33:50','EST'), 'yyyyMMddHHmmss') from dual

你是这个意思吗?

【讨论】:

    【解决方案2】:

    您只需将 0 添加到您的字段中,例如:

    SELECT datetimefield+0;
    
    SELECT CONVERT_TZ('2017-02-02 07:32:51','EST','GMT');
    

    如果 CONVERT_TZ 返回 NULL,您可以安装时区表,例如:

    mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
    

    样本

    mysql> SELECT CONVERT_TZ('2017-02-02 07:32:51','EST','GMT');
    +-----------------------------------------------+
    | CONVERT_TZ('2017-02-02 07:32:51','EST','GMT') |
    +-----------------------------------------------+
    | 2017-02-02 12:32:51                           |
    +-----------------------------------------------+
    1 row in set (0,00 sec)
    
    mysql>
    mysql> SELECT DATE(TIMESTAMP('2017-02-02 07:32:51'))+0;
    +------------------------------------------+
    | DATE(TIMESTAMP('2017-02-02 07:32:51'))+0 |
    +------------------------------------------+
    |                                 20170202 |
    +------------------------------------------+
    1 row in set (0,00 sec)
    
    mysql> select id, mydate, date(mydate), date(mydate)+0 from df;
    +----+---------------------+--------------+----------------+
    | id | mydate              | date(mydate) | date(mydate)+0 |
    +----+---------------------+--------------+----------------+
    |  1 | 2017-02-05 03:33:50 | 2017-02-05   |       20170205 |
    +----+---------------------+--------------+----------------+
    1 row in set (0,00 sec)
    
    mysql>
    
    mysql> SELECT TIMESTAMP('2017-02-05 03:33:50')+0;
    +------------------------------------+
    | TIMESTAMP('2017-02-05 03:33:50')+0 |
    +------------------------------------+
    |                     20170205033350 |
    +------------------------------------+
    1 row in set (0,00 sec)
    
    mysql>
    mysql> select id, mydate, mydate+0 from df;
    +----+---------------------+----------------+
    | id | mydate              | mydate+0       |
    +----+---------------------+----------------+
    |  1 | 2017-02-05 03:33:50 | 20170205033350 |
    +----+---------------------+----------------+
    1 row in set (0,00 sec)
    
    mysql>
    

    【讨论】:

    • 感谢分享,但更改格式不是我的问题,我想将更改后的时间格式转换为 gmt 时区。
    • 对不起,我在我的答案中添加了一个转换时区示例
    【解决方案3】:

    假设您想要一个 Hive 查询,这就是我如何将 Hive 时间戳列(使用当前系统时区)转换为 Impala 时间戳(使用与 GMT 相同的 UTC,但不推荐使用 GMT) .

    CREATE TEMPORARY MACRO to_impala_timestamp(ts TIMESTAMP)
      CAST(FROM_UNIXTIME(UNIX_TIMESTAMP(ts) +CAST(CAST(PRINTF('%tz', ts) AS FLOAT)*36.0 AS INT)) AS TIMESTAMP)
    ;
    --## WARNING - do not use MACROs if your Hive version is below V1.3 (Apache, Horton)
    --## or below V1.1-CDH5.7.3, V1.1-CDH5.8.3, V1.1-CDH5.9.0 (Cloudera)
    --## cf. "HIVE-11432 Hive macro give same result for different arguments"
    

    PRINTF('%tz', ts) 将提取时区,动态处理夏令时 -- 假设您正在处理的时间戳与 系统时区相关 由您的 Hadoop 集群使用。如果是不同的 TZ,那么您必须相应地调整宏。

    您可以使用以下查询对其进行测试:

    CREATE TABLE test_tz
    STORED AS Parquet
    AS
    SELECT CAST(ts AS STRING) AS initial_ts_as_string
      , printf('%1$tz %1$tZ', ts) AS tzone_offset_and_code
      , ts AS ts_for_hive
      , to_impala_timestamp(ts) AS ts_for_impala
    FROM ...
    

    我们的集群使用中欧时间,这就是结果在 Hive 中的显示方式...

    +--------------------------+--------------------+-----------------------------+-------------------------+
    |  initial_ts_as_string    | tz_offset_and_code | ts_for_hive                 | ts_for_impala           |
    +--------------------------+--------------------+-----------------------------+-------------------------+
    | 2015-09-13 11:32:30.627  | +0200 CEST         | 2015-09-13 11:32:30.627     | 2015-09-13 13:32:30.0   |
    | 2015-12-10 12:27:01.282  | +0100 CET          | 2015-12-10 12:27:01.282     | 2015-12-10 13:27:01.0   |
    | 2016-05-17 15:49:06.386  | +0200 CEST         | 2016-05-17 15:49:06.386     | 2016-05-17 17:49:06.0   |
    

    ...然后在 Impala 中...

    +-------------------------+--------------------+-------------------------------+---------------------+
    |  initial_ts_as_string   | tz_offset_and_code | ts_for_hive                   | ts_for_impala       |
    +-------------------------+--------------------+-------------------------------+---------------------+
    | 2015-09-13 11:32:30.627 | +0200 CEST         | 2015-09-13 09:32:30.627000000 | 2015-09-13 11:32:30 |
    | 2015-12-10 12:27:01.282 | +0100 CET          | 2015-12-10 11:27:01.282000000 | 2015-12-10 12:27:01 |
    | 2016-05-17 15:49:06.386 | +0200 CEST         | 2016-05-17 13:49:06.386000000 | 2016-05-17 15:49:06 |
    

    请注意,运行转换时会丢失毫秒;他们可以通过一个额外的技巧来恢复,但通常这超出了重点。


    旁注:要将时间戳(或日期或浮点数或其他)格式化为字符串,好的旧 Java PRINTF() 函数比使用默认格式加上 REGEXP_***() 函数更实用......

    【讨论】:

      【解决方案4】:

      感谢您提供的所有解决方案

      这里的所有答案都有部分解决方案,使用答案资源我尝试了以下语法并且有效。

      cast(substr(regexp_replace(to_utc_timestamp(timestamp_column, 'EST') ,'-',''),1,8) as int) as dt_skey
      

      为了解释上述语法,这是我的时间戳列的样子 (yyyy-MM-dd HH:mm:ss) "2017-02-16 12:20:21"

      运行上述语法后,我的输出将类似于“20170216”,即“yyyyMMdd” regexp_replace 将执行正则表达式以仅显示 yyyyMMdd。 to_utc_timestamp(timestamp_column, 'EST') 会将时间戳列转换为 UTC 时区。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-22
        • 2012-07-04
        • 2018-04-13
        • 1970-01-01
        • 2016-11-12
        相关资源
        最近更新 更多