Azure 数据资源管理器中的时区感知查询

Timezone-aware queries in Azure Data Explorer

我使用 Azure 数据资源管理器来存储温度传感器值。时间戳采用 UTC。我想在过去 7 天按天汇总这些值。不过,我想使用这些值来自的当地时间,并按当地时间的时间戳进行汇总(例如,午夜将在 00:00+2h 和 22:00UTC)。如何在 ADX 中使用 Kusto 查询语言执行此操作?

Azure 数据资源管理器没有任何用于在时区之间进行转换的内置函数。

The documentation推荐:

... Should time zone values be required to be kept as a part of the data, a separate columns should be used (providing offset information relative to UTC).

因此,您应该存储 两个 值 - 原始的基于 UTC 的时间戳,以便您可以正确排序数据,以及本地时区的日期,以便您可以通过当地时间。

例如如果您想提供时区 UTC+1,您可以通过以下方式扩展您的 Kusto 查询:

| extend Timestamp = Timestamp + 3600s

您的时间范围过滤器仍需要以 UTC 格式提供。

偏移量有效,但如果您关心夏令时并且有一个非常通用的解决方案,则不能简单地使用时区的固定偏移量。如果您要定期生成报告并且时区必须正确,请继续阅读。

感觉有点像 hack,但我们按照这些思路取得成果的方法是创建一个时区 table,其中包含如下列:

BeginOfDay: datetime(2020-01-01 00:00:00)
Timezone: "Africa/Addis_Ababa"
UTCStart: datetime(2020-01-01 00:00:00)-3h
UTCEnd: datetime(2020-01-02 00:00:00)-3h

每个时区和感兴趣的日期的组合都应该占一行。我们填充了大约十年后的未来。如果您担心存储 space 或速度,您只需要包括您关心的日期范围和时区,但即使使用 'everything' 它也不是很大 table。

每行包含 'day' BeginOfDay,它总是午夜,相当于 "The first of January, 2020",然后是本地日期的开始和结束时间,以 UTC 时间表示。我们写了一个程序来生成table的内容,当然

之后,您可以执行以下操作:

let TimezoneDay = datatable (BeginOfDay:datetime, Timezone:string, UTCStart:datetime, UTCEnd:datetime)
    [datetime(2020-01-01), "Africa/Addis_Ababa", datetime(2019-12-31 21:00:00), datetime(2020-01-01 21:00:00), 
     datetime(2020-01-02), "Africa/Addis_Ababa", datetime(2020-01-01 21:00:00), datetime(2020-01-02 21:00:00), 
     datetime(2020-01-03), "Africa/Addis_Ababa", datetime(2020-01-02 21:00:00), datetime(2020-01-03 21:00:00)
     ];
let TemperatureEvents = datatable (Timestamp:datetime, Device:string, Temperature:real) 
    [datetime(2020-01-01 05:00:00), "Device 1", 10.5,
     datetime(2020-01-01 07:00:00), "Device 1", 30.5,
     datetime(2020-01-02 01:50:00), "Device 1", 24.0,
     datetime(2020-01-02 20:00:00), "Device 1", 20.5,
     datetime(2020-01-02 23:50:00), "Device 1", 19.5,
     datetime(2020-01-01 10:20:00), "Device 2", 0.5
    ];
TimezoneDay
| where Timezone == "Africa/Addis_Ababa"
// Use a dummy column to emulate a cross join
| extend dummy=1
| join kind=inner (TemperatureEvents | extend dummy = 1) on dummy
// Filter values into local time
| where Timestamp between (UTCStart .. UTCEnd)
| summarize AverageTemp=avg(Temperature) by BeginOfDay, Timezone, Device

如果你有一个大数据集,交叉连接可能会有点贵,但这是一个起点 - 你也可以做一个时间 window 连接来限制你考虑的每个事件的数量 'day'.