簡體   English   中英

將 UTC 時間轉換為 Azure ADX Kusto 查詢中的特定時區

[英]Convert UTC time to specific time zone in Azure ADX Kusto query

我在 Azure 數據資源管理器中有數百萬條記錄。 每條記錄都有一個與之關聯的時間戳值。 我希望能夠在特定時區轉換此時間戳值。

例如在 SQL 我使用 AT TIME ZONE 將時間戳值從一個區域轉換為另一個 -

Select CONVERT(datetime, timestampvalueColumn) AT TIME ZONE 'UTC' AT TIME ZONE 'US Eastern Standard Time' as 'TimeInEST' from Table;

我不願意使用偏移值,因為它不支持夏令時更改。

如何使用 ADX 中的 Kusto 查詢語言做到這一點?

幸運的是,美國東部時間是一個相對簡單的例子。
下面的代碼適用於 2007 年及以后范圍內的日期。

在美國,夏令時從 3 月的第二個星期日當地時間凌晨 2:00 開始。
在 11 月的第一個星期日,夏令時地區的凌晨 2:00 恢復為標准時間
當美國開始夏令時時,將時鍾提前一小時。 在夏令時結束時,將時鍾撥回一小時。

https://www.timetemperature.com/tzus/daylight_saving_time.shtml

// Sample generation. Not part of the solution
let t = materialize(range i from 1 to 15 step 1 | extend dt_utc = ago(rand()*365d*10));
// Solution Starts here
let et2utc_mar_2nd_sun_2am  = (dt_utc:datetime){make_datetime(getyear(dt_utc),3,1,2,0,0) + (7d - dayofweek(make_datetime(getyear(dt_utc),3,1)))%7d + 7d + 5h};
let et2utc_nov_2nd_sun_2am  = (dt_utc:datetime){make_datetime(getyear(dt_utc),11,1,2,0,0) + (7d - dayofweek(make_datetime(getyear(dt_utc),3,1)))%7d + 4h};
let EasternTimeOffset       = (dt_utc:datetime){iff(dt_utc between (et2utc_mar_2nd_sun_2am(dt_utc) .. et2utc_nov_2nd_sun_2am(dt_utc)), -4h, -5h)};
t
| extend EasternTimeOffset = EasternTimeOffset(dt_utc)
| extend EasternTime = dt_utc + EasternTimeOffset
一世 dt_utc 東部時間偏移 東部時間
2 2013-01-02T09:46:21.2553241Z -05:00:00 2013-01-02T04:46:21.2553241Z
12 2013-04-29T19:53:51.3170521Z -04:00:00 2013-04-29T15:53:51.3170521Z
1 2013-09-03T18:31:31.2211331Z -04:00:00 2013-09-03T14:31:31.2211331Z
11 2013-09-25T13:45:33.3380811Z -04:00:00 2013-09-25T09:45:33.3380811Z
8 2013-10-02T23:44:54.8682621Z -04:00:00 2013-10-02T19:44:54.8682621Z
15 2014-03-30T12:44:47.6381621Z -04:00:00 2014-03-30T08:44:47.6381621Z
10 2015-02-21T15:34:46.8657901Z -05:00:00 2015-02-21T10:34:46.8657901Z
9 2016-06-16T19:44:31.0144371Z -04:00:00 2016-06-16T15:44:31.0144371Z
3 2016-10-21T04:03:51.0185641Z -04:00:00 2016-10-21T00:03:51.0185641Z
5 2017-11-11T01:50:21.6729811Z -05:00:00 2017-11-10T20:50:21.6729811Z
14 2017-12-02T01:02:18.3206731Z -05:00:00 2017-12-01T20:02:18.3206731Z
7 2018-11-06T06:00:52.4156001Z -05:00:00 2018-11-06T01:00:52.4156001Z
13 2019-11-18T14:05:15.4887631Z -05:00:00 2019-11-18T09:05:15.4887631Z
4 2021-02-16T01:02:37.7791421Z -05:00:00 2021-02-15T20:02:37.7791421Z
6 2021-07-28T04:16:18.3716831Z -04:00:00 2021-07-28T00:16:18.3716831Z

小提琴

基於Python插件

熊貓相關文檔: tz_localizetz_convertstrftime

// Sample generation. Not part of the solution
let t = materialize(range i from 1 to 15 step 1 | extend dt_utc = bin(ago(rand()*365d*10), 1s));
// Solution Starts here
let p_schema = typeof(*, dt_et:datetime);
let p_arguments = dynamic({"TZ" : "US/Eastern"});
let p_script =
```
iso_fmt = "%Y-%m-%d %H:%M:%S"
result = df
result["dt_et"] = df["dt_utc"].dt.tz_localize("UTC").dt.tz_convert(kargs["TZ"]).dt.strftime(iso_fmt)
```;
t
| evaluate  python(p_schema, p_script, p_arguments)
| extend    offset = dt_et - dt_utc
一世 dt_utc dt_et 抵消
5 2013-03-20T02:43:54Z 2013-03-19T22:43:54Z -04:00:00
11 2013-03-20T04:29:50Z 2013-03-20T00:29:50Z -04:00:00
15 2013-05-12T06:03:49Z 2013-05-12T02:03:49Z -04:00:00
8 2014-02-21T22:23:32Z 2014-02-21T17:23:32Z -05:00:00
13 2015-12-26T08:55:41Z 2015-12-26T03:55:41Z -05:00:00
2 2016-06-09T10:53:04Z 2016-06-09T06:53:04Z -04:00:00
4 2016-12-17T21:19:15Z 2016-12-17T16:19:15Z -05:00:00
10 2017-06-23T06:54:48Z 2017-06-23T02:54:48Z -04:00:00
7 2017-07-25T21:12:58Z 2017-07-25T17:12:58Z -04:00:00
1 2019-12-05T16:43:48Z 2019-12-05T11:43:48Z -05:00:00
3 2019-12-18T17:20:17Z 2019-12-18T12:20:17Z -05:00:00
12 2019-12-30T02:51:46Z 2019-12-29T21:51:46Z -05:00:00
14 2021-01-31T08:36:00Z 2021-01-31T03:36:00Z -05:00:00
6 2021-04-25T13:31:14Z 2021-04-25T09:31:14Z -04:00:00
9 2021-07-15T11:20:58Z 2021-07-15T07:20:58Z -04:00:00

站點http://web.cs.ucla.edu/~eggert/tz/tz-link.htm指向站點https://timezonedb.com/download ,該站點具有https://www.iana.org/ csv 格式的時區站點數據。
它包含所有時區的夏令時更改的過去和未來(盡可能多)。

下面對演示的幾點說明:

  • 我已將 csv 文件加載到我的 ADLS 中,並且正在使用externaldata運算符讀取它,但您當然可以將其攝取到永久表中。
  • 我在這里將 UTC 日期時間轉換為 America/New_York,但您也可以使用任何其他時區。
  • 此處使用mv-expand運算符來提高連接性能(使用查找運算符實現)。

// Sample data generation. Not part of the solution
let t = 
materialize(range i from 1 to 15 step 1 | extend dt_utc = bin(ago(rand()*365d*10), 1s))
;
// Solution Starts here
let time_zone = 
externaldata(zone_name:string, country_code:string, tz_abbreviation:string,  unixtime_start:long, gmt_offset_seconds:int, is_dst:bool)
[
    h"https://dumarkovadlsgen2.dfs.core.windows.net/mycontainer/TimeZoneDB/time_zone.csv;impersonate"
]
with (format=csv)
|   where   zone_name == "America/New_York"
|   extend  gmt_offset = gmt_offset_seconds * 1s
|   extend  datetime_start = unixtime_seconds_todatetime(unixtime_start)
|   project datetime_start, gmt_offset
;
let time_zone_dst_range = 
time_zone
|   order by    datetime_start asc
|   extend      next_datetime_start = next(datetime_start, 1, datetime(9999))
|   mv-expand   year = range(getyear(datetime_start), getyear(next_datetime_start)) to typeof(long)
;
t
|   extend  year = getyear(dt_utc)
|   lookup  time_zone_dst_range on year 
|   where   dt_utc >= datetime_start and dt_utc < next_datetime_start
|   extend  et_utc = dt_utc + gmt_offset
一世 dt_utc 日期時間開始 gmt_offset next_datetime_start et_utc
10 2014-05-12T02:03:38Z 2014 2014-03-09T07:00:00Z -04:00:00 2014-11-02T06:00:00Z 2014-05-11T22:03:38Z
13 2014-12-26T21:46:29Z 2014 2014-11-02T06:00:00Z -05:00:00 2015-03-08T07:00:00Z 2014-12-26T16:46:29Z
11 2015-01-04T03:04:33Z 2015 2014-11-02T06:00:00Z -05:00:00 2015-03-08T07:00:00Z 2015-01-03T22:04:33Z
4 2016-12-02T13:34:42Z 2016 年 2016-11-06T06:00:00Z -05:00:00 2017-03-12T07:00:00Z 2016-12-02T08:34:42Z
12 2017-03-13T04:20:32Z 2017 2017-03-12T07:00:00Z -04:00:00 2017-11-05T06:00:00Z 2017-03-13T00:20:32Z
2 2017-10-18T01:52:22Z 2017 2017-03-12T07:00:00Z -04:00:00 2017-11-05T06:00:00Z 2017-10-17T21:52:22Z
9 2018-08-15T06:00:49Z 2018 2018-03-11T07:00:00Z -04:00:00 2018-11-04T06:00:00Z 2018-08-15T02:00:49Z
7 2018-10-03T00:56:55Z 2018 2018-03-11T07:00:00Z -04:00:00 2018-11-04T06:00:00Z 2018-10-02T20:56:55Z
5 2018-12-09T08:02:56Z 2018 2018-11-04T06:00:00Z -05:00:00 2019-03-10T07:00:00Z 2018-12-09T03:02:56Z
6 2018-12-31T19:41:15Z 2018 2018-11-04T06:00:00Z -05:00:00 2019-03-10T07:00:00Z 2018-12-31T14:41:15Z
15 2019-02-07T01:19:59Z 2019 2018-11-04T06:00:00Z -05:00:00 2019-03-10T07:00:00Z 2019-02-06T20:19:59Z
1 2020-03-06T06:18:07Z 2020 2019-11-03T06:00:00Z -05:00:00 2020-03-08T07:00:00Z 2020-03-06T01:18:07Z
14 2020-04-03T21:52:31Z 2020 2020-03-08T07:00:00Z -04:00:00 2020-11-01T06:00:00Z 2020-04-03T17:52:31Z
8 2021-03-27T00:15:46Z 2021 2021-03-14T07:00:00Z -04:00:00 2021-11-07T06:00:00Z 2021-03-26T20:15:46Z
3 2021-09-23T01:17:10Z 2021 2021-03-14T07:00:00Z -04:00:00 2021-11-07T06:00:00Z 2021-09-22T21:17:10Z

通常答案是“不要在 Kusto 中執行”,在從 Kusto 讀取結果的客戶端中執行,這肯定會有“utc-to-local-time”或“utc-to-this-時區”功能。

好吧,Kusto 團隊正在快速行動:-)

添加了對時區轉換的支持:

  • datetime_local_to_utc()
  • datetime_utc_to_local()

// Sample generation. Not part of the solution
let t = materialize(range i from 1 to 15 step 1 | extend dt_utc = ago(rand()*365d*10));
// Solution Starts here
t
| extend dt_et = datetime_utc_to_local(dt_utc, "US/Eastern")
| extend offset = dt_et - dt_utc
一世 dt_utc dt_et 抵消
5 2012-12-03T17:24:51.6057076Z 2012-12-03T12:24:51.6057076Z -05:00:00
14 2012-12-10T05:04:17.8507406Z 2012-12-10T00:04:17.8507406Z -05:00:00
10 2013-03-23T14:42:00.4276416Z 2013-03-23T10:42:00.4276416Z -04:00:00
15 2013-10-01T06:28:36.4665806Z 2013-10-01T02:28:36.4665806Z -04:00:00
11 2017-07-18T06:10:30.9963876Z 2017-07-18T02:10:30.9963876Z -04:00:00
3 2017-11-17T21:57:58.4443366Z 2017-11-17T16:57:58.4443366Z -05:00:00
6 2018-05-09T03:36:24.7533896Z 2018-05-08T23:36:24.7533896Z -04:00:00
12 2018-06-05T17:36:41.7970716Z 2018-06-05T13:36:41.7970716Z -04:00:00
4 2018-08-03T16:25:19.9323686Z 2018-08-03T12:25:19.9323686Z -04:00:00
8 2019-02-21T17:33:52.9957996Z 2019-02-21T12:33:52.9957996Z -05:00:00
2 2020-09-24T18:37:08.0049776Z 2020-09-24T14:37:08.0049776Z -04:00:00
1 2020-12-09T19:57:23.7480626Z 2020-12-09T14:57:23.7480626Z -05:00:00
7 2021-01-17T13:42:55.0632136Z 2021-01-17T08:42:55.0632136Z -05:00:00
9 2021-03-04T23:44:01.7192366Z 2021-03-04T18:44:01.7192366Z -05:00:00
13 2022-06-04T16:26:57.8826486Z 2022-06-04T12:26:57.8826486Z -04:00:00

小提琴

您可以使用下面給出的 function 的類似想法構建一個方便的 function。 請注意,轉換也適用於 DST(夏令時)。 您只需要一種方法將 map 放置到其時區字符串中。 在隨后的 function 中,映射是從巴西 state 縮寫到其時區字符串。 有關可用時區的列表,請參閱文檔

.create-or-alter function with (
    docstring = 'Dada uma UF e um datetime (UTC), retorna o horário local. Não é tratado o GMT-5 ao oeste de AM.' ) ToLocalDatetime(state: string, dtutc: datetime) {
    let selected_tz = materialize(datatable(states:string, tz:string) [
        'GO,DF,MG,ES,RJ,SP,PR,SC,RS', 'America/Sao_Paulo',
        'MA,PI,CE,RN,PB', 'America/Fortaleza',
        'AL,SE', 'America/Maceio',
        'BA', 'America/Bahia',
        'RR', 'America/Boa_Vista',
        'MS', 'America/Campo_Grande',
        'MT', 'America/Cuiaba',
        'AM', 'America/Manaus',
        'PA,AP', 'America/Belem',
        'AC', 'America/Rio_Branco',
        'RO', 'America/Porto_Velho',
        'PE', 'America/Recife',
        'TO', 'America/Araguaina'
    ]
    | where states has state | project tz);
    let localdt = datetime_utc_to_local(dtutc, toscalar(selected_tz));
    format_datetime(localdt, "yyyy-MM-dd HH:mm:ss") }

幾個測試:

print(ToLocalDatetime('DF', datetime('2019-02-17 01:00:00')))
print(ToLocalDatetime('DF', datetime('2019-02-17 02:00:00')))

Z78E6221F6393D135681DB398F14CE6DZ在兩種情況下均為2019-02-16 23:00:00 (本地DF Z9ED39E2EA9E2EA9E2EA931586B6B6A985A6942EF573EZ TIME),因為DST11191913913919913919191919191911911191191919191191191199119911991191191191199119919913991391.1A991391390AN39999性小小士范站范文發發 /設2019-02-17 02:00:00Z

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM