【问题标题】:Big Query how to convert string to dateBig Query如何将字符串转换为日期
【发布时间】:2017-12-20 14:31:13
【问题描述】:

我有一些日期时间类型的列作为字符串推入 BQ。它们的格式为:Wed Dec 20 02:54:35 GMT 2017

我希望将它们转换为正确的日期时间,以便我可以执行一些操作,例如计算以毫秒为单位的时间差等。我尝试了日期、强制转换,但似乎没有任何效果。他们都回零。

例如,采用以下 2 个日期时间: startTime = Wed Dec 20 02:54:35 GMT 2017 endTime = Wed Dec 20 02:54:36 GMT 2017

我想计算时间差异(以秒或毫秒为单位)。

【问题讨论】:

    标签: google-bigquery


    【解决方案1】:

    我希望将它们转换为正确的日期时间,以便我可以执行一些操作,例如计算以毫秒为单位的时间差等。

    以下是 BigQuery 标准 SQL,理想情况下应该适用于您介绍的示例

    #standardSQL
    SELECT startTime, endTime,
      TIMESTAMP_DIFF(
        PARSE_TIMESTAMP('%a %b %d %H:%M:%S %Z %Y', endTime), 
        PARSE_TIMESTAMP('%a %b %d %H:%M:%S %Z %Y', startTime), 
        MILLISECOND
      ) diff_in_ms
    FROM `yourproject.yourdataset.yourtable`   
    

    您可以使用下面的虚拟数据测试/玩它

    #standardSQL
    WITH `yourproject.yourdataset.yourtable` AS (
      SELECT 'Wed Dec 20 02:54:35 GMT 2017' startTime, 'Wed Dec 20 02:54:36 GMT 2017' endTime
    )
    SELECT startTime, endTime,
      TIMESTAMP_DIFF(
        PARSE_TIMESTAMP('%a %b %d %H:%M:%S %Z %Y', endTime), 
        PARSE_TIMESTAMP('%a %b %d %H:%M:%S %Z %Y', startTime), 
        MILLISECOND
      ) diff_in_ms
    FROM `yourproject.yourdataset.yourtable`   
    

    我也完全可以删除时区

    看起来你对 PST 有问题 - 你可以尝试在下面消除时区

    #standardSQL
    CREATE TEMP FUNCTION removeTZ(val STRING) AS (
      REGEXP_REPLACE(val, r'(\w+ \w+ \d{2} \d{2}:\d{2}:\d{2} )\w+ (\d{4})', '\\1\\2')
    );
    SELECT startTime, endTime,
      TIMESTAMP_DIFF(
        PARSE_TIMESTAMP('%a %b %d %H:%M:%S %Y', removeTZ(endTime)), 
        PARSE_TIMESTAMP('%a %b %d %H:%M:%S %Y', removeTZ(startTime)), 
        MILLISECOND
      ) diff_in_ms
    FROM `yourproject.yourdataset.yourtable`   
    

    您仍然可以使用相同的虚拟数据进行测试/玩

    #standardSQL
    CREATE TEMP FUNCTION removeTZ(val STRING) AS (
      REGEXP_REPLACE(val, r'(\w+ \w+ \d{2} \d{2}:\d{2}:\d{2} )\w+ (\d{4})', '\\1\\2')
    );
    WITH `yourproject.yourdataset.yourtable` AS (
      SELECT 'Wed Dec 20 02:54:35 GMT 2017' startTime, 'Wed Dec 20 02:54:36 GMT 2017' endTime
    )
    SELECT startTime, endTime,
      TIMESTAMP_DIFF(
        PARSE_TIMESTAMP('%a %b %d %H:%M:%S %Y', removeTZ(endTime)), 
        PARSE_TIMESTAMP('%a %b %d %H:%M:%S %Y', removeTZ(startTime)), 
        MILLISECOND
      ) diff_in_ms
    FROM `yourproject.yourdataset.yourtable`   
    

    上述两个查询都返回相同的结果(当然)

    startTime                       endTime                         diff_in_ms   
    Wed Dec 20 02:54:35 GMT 2017    Wed Dec 20 02:54:36 GMT 2017    1000     
    

    注意:第二种解决方案(消除时区)不依赖于预定义的位置/长度,因为时区可以有不同的长度。相反,它使用正则表达式来识别时区并将其删除

    【讨论】:

      【解决方案2】:

      尝试使用PARSE_TIMESTAMP

      SELECT
          PARSE_TIMESTAMP('%a %b %d %H:%M:%S %Z %Y', 'Wed Dec 20 02:54:35 GMT 2017')
      FROM yourTable;
      

      从上述 SQL 的冗长中可以看出,如果您需要将日期作为实际日期进行处理,那么将日期存储为文本是很麻烦的。相反,请始终将日期/时间戳存储在适当的日期列中。

      我们可以尝试不分时区解析:

      SELECT
          PARSE_TIMESTAMP('%a %b %d %H:%M:%S %Y',
              CONCAT(SUBSTR(col, 1, 20), SUBSTR(col, 25, 4)))
      FROM yourTable;
      

      【讨论】:

      • 我收到一个错误:Error: 3.17 - 3.57: Unrecognized function parse_timestamp
      • 如果您将 Bi​​g Query 与标准 SQL 一起使用,上述内容应该可以工作。你不这样做吗?
      • 我的错,它处于旧版 sql 模式。我禁用了它,然后该功能可用。但是现在它抱怨以下内容:Error: Invalid time zone: PST
      • 奇怪,因为PSTstandard time zone abbreviation。尽管您没有收到 GMT 的错误,但这表明查询至少部分工作。
      • 这很奇怪。我位于 PST 时区。当原始日期字符串显式采用 GMT 格式时,为什么这与转换有任何关系?有什么想法吗?
      猜你喜欢
      • 2019-08-18
      • 2020-11-11
      • 2020-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多