2

I use the Azure Data Explorer to store temperature sensor values. The timestamps are in UTC. I want to aggregate these values by day for the last 7 days. Nevertheless, I want to use the local time from where these values came from and aggregate by the timestamps in local time (e.g. midnight would be at 00:00+2h and 22:00UTC). How can I do this with Kusto Query Language in the ADX?

Thomas Hahn
  • 171
  • 1
  • 2
  • 12
  • Please share your sample KQL along with current result screenshot so we can understand the structure and suggest solution. – Indar May 20 '20 at 08:45
  • 2
    Do you have the offset of the local time from UTC? you can create a new column based on this offset which is the local time and do the aggregation based on that column. – Avnera May 20 '20 at 10:08
  • **See Also**: [Convert UTC 'TimeGenerated' to local time in Azure monitor/log/analytics, when using "summarize by"](https://stackoverflow.com/q/59393428/1366033) – KyleMit Oct 20 '21 at 14:17
  • Maybe this answer helps https://stackoverflow.com/a/73839343/2013900 – Rodrigo Nogueira Sep 24 '22 at 17:49

3 Answers3

5

E.g. if you want to provide the timezone UTC+1, you can extend your Kusto query by this:

| extend Timestamp = Timestamp + 3600s

Your filters for a time range would still need to be provided in UTC though.

Thomas Hahn
  • 171
  • 1
  • 2
  • 12
  • Worked great for me! Only tweak I had to make was making timestamp lowercase. Capitalized threw an error. – Stan Aug 05 '22 at 12:27
2

Offsets work, but you cannot simply use a fixed offset for time zone if you care about daylight saving and having a very general solution. If you're doing something that regularly produces reports AND the time zone must be correct, read on.

It felt like a bit of a hack, but the way we achieved something along these lines was to create a time zone table with columns like this:

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

There should be one row for every combination of time zone and day of interest. We populated something like ten years into the future. If you're worried about storage space or speed you only need to include the date range and time zones you care about, but even with 'everything' it was not a very large table.

Each row contains the 'day' BeginOfDay, which is always midnight and equivalent to "The first of January, 2020", and then the start and end of that local day in, in UTC time. We wrote a program to generate the contents of the table, of course.

After that, you can do something like:

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

The cross join may be a little expensive if you have a large dataset, but this is a starting point - you can also do a time window join to restrict the number of events you consider for each 'day'.

joelby
  • 87
  • 8
1

Azure Data Explorer doesn't have any built-in functions for converting between time zones.

The documentation recommends:

... 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).

Thus, you should store two values - The original UTC-based timestamp so you can properly order the data, and the date from the local time zone so you can aggregate by local day.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575