【问题标题】:Get number of milliseconds for a localised date, taking into account daylight savings获取本地化日期的毫秒数,考虑夏令时
【发布时间】:2019-09-05 01:43:30
【问题描述】:

我在 Google BigQuery 中有如下所示的数据:


sample_date_time_UTC     time_zone       milliseconds_between_samples
--------                 ---------       ----------------------------
2019-03-31 01:06:03 UTC  Europe/Paris    60000
2019-03-31 01:16:03 UTC  Europe/Paris    60000
...

数据样本需要定期进行,由 milliseconds_between_samples 字段的值指示:

time_zone 是一个字符串,代表 Google Cloud Supported Timezone Value


然后,我会检查任何一天范围内的实际样本数量与预期数量的比率(表示为本地日期,对于给定的time_zone):

with data as 
  ( 
    select 
      -- convert sample_date_time_UTC to equivalent local datetime for the timezone
      DATETIME(sample_date_time_UTC,time_zone) as localised_sample_date_time, 
      milliseconds_between_samples 
    from  `mytable` 
    where sample_date_time between '2019-03-31 00:00:00.000000+01:00' and '2019-04-01 00:00:00.000000+02:00'
  ) 

select date(localised_sample_date_time) as localised_date, count(*)/(86400000/avg(milliseconds_between_samples)) as ratio_of_daily_sample_count_to_expected 
from data 
group by localised_date 
order by localised_date 

问题在于这有一个错误,因为我已将一天中的预期毫秒数硬编码为86400000。这是不正确的,因为当夏令时在指定的time_zone (Europe/Paris) 开始时,一天缩短了 1 小时。夏令时结束后,白天会延长 1 小时。

所以,上面的查询是不正确的。它在Europe/Paris 时区(即该时区开始夏令时)查询今年 3 月 31 日的数据。当天的毫秒数应该是82800000

在查询中,如何获取指定localised_date 的正确毫秒数?

更新:

我试着这样做看看它会返回什么:

select DATETIME_DIFF(DATETIME('2019-04-01 00:00:00.000000+02:00', 'Europe/Paris'), DATETIME('2019-03-31 00:00:00.000000+01:00', 'Europe/Paris'), MILLISECOND)

那没用 - 我收到 86400000

【问题讨论】:

    标签: datetime google-bigquery dst


    【解决方案1】:

    您可以通过删除+01:00+02:00 来获得两个时间戳的毫秒差异。请注意,这给出了 UTC 时间戳之间的差异:90000000,这与实际经过的毫秒数不同。

    您可以执行以下操作来获取一天的毫秒数:

    select 86400000 + (86400000 - DATETIME_DIFF(DATETIME('2019-04-01 00:00:00.000000', 'Europe/Paris'), DATETIME('2019-03-31 00:00:00.000000', 'Europe/Paris'), MILLISECOND))
    

    【讨论】:

      【解决方案2】:

      感谢@Juta,提供有关使用 UTC 时间进行计算的提示。当我按本地化日期对每天的数据进行分组时,我发现我可以使用以下逻辑通过获取“本地化”日期的开始和结束日期时间(UTC)来计算每天的毫秒数:

      -- get UTC start datetime for localised date
      -- get UTC end datetime for localised date
      
      -- this then gives the milliseconds for that localised date:
      datetime_diff(utc_end_datetime, utc_start_datetime, MILLISECOND);
      

      所以,我的完整查询变为:

      with daily_sample_count as (
        with data as 
          ( 
            select 
              -- get the date in the local timezone, for sample_date_time_UTC
              DATE(sample_date_time_UTC,time_zone) as localised_date, 
              milliseconds_between_samples 
            from  `mytable` 
            where sample_date_time between '2019-03-31 00:00:00.000000+01:00' and '2019-04-01 00:00:00.000000+02:00'
          ) 
      
        select
          localised_date,
          count(*) as daily_record_count,
          avg(milliseconds_between_samples) as daily_avg_millis_between_samples,
          datetime(timestamp(localised_date, time_zone)) as utc_start_datetime,
          datetime(timestamp(date_add(localised_date, interval 1 day), time_zone)) as utc_end_datetime
        from data 
      )
      
      select
        localised_date,
        -- apply calculation for ratio_of_daily_sample_count_to_expected
        -- based on the actual vs expected number of samples for the day
        -- no. of milliseconds in the day changes, when transitioning in/out of daylight saving - so we calculate milliseconds in the day
        daily_record_count/(datetime_diff(utc_end_datetime, utc_start_datetime, MILLISECOND)/daily_avg_millis_between_samples) as ratio_of_daily_sample_count_to_expected
      from
        daily_sample_count
      

      【讨论】:

        猜你喜欢
        • 2015-10-24
        • 2018-02-04
        • 2012-09-08
        • 2014-03-02
        • 2013-09-18
        • 1970-01-01
        • 2011-08-14
        • 2021-01-21
        • 2013-09-22
        相关资源
        最近更新 更多