Time Zones in Flux

4 minutes

As a language for processing time series data, Flux has an important role in how we understand that data. As we create and process data, we do it for ourselves and others.

The concept of time and how we as people interact with time isn’t always simple. Most of us have to adjust our schedules at least twice a year because of daylight savings time, and sometimes we have to adjust our clocks in more complex ways because — for important political, cultural, or economic reasons — we need to have our clocks read a certain time such as skipping a day.

Flux before time zone support

Flux is a language for time series data and, until recently, Flux wasn’t able to understand these subtleties. Flux would do all of its work in UTC, which is a simple linear clock, and leave it to the user to figure out the display. This works well for most circumstances! It’s what Flux should be doing! Flux shouldn’t be involved in figuring out the correct way to display the time zone. The InfluxDB UI is very capable of figuring that out better than Flux would ever be able to. In situations like monitoring servers, UTC is perfect and should be used over a specific time zone.

But…what happens when we start to aggregate data for other purposes? What if I want to aggregate by days, weeks, or months and I want these aggregations to be in my own time zone for a business reason? I don’t live in the UK and, even if I did, the UK isn’t on UTC time the entire year anyway. I can just pretend and remember that my aggregations aren’t 100% accurate all the time and they are “good enough”. Sometimes “good enough” isn’t good enough. In those, I can get closer by using an offset to shift the time to my time zone. But, when daylight savings time happens, I might be back to “good enough” aggregation by time.

Time zone support in Flux

Flux now features full time zone support for those who need to perform their aggregations within a specific time zone.

To enable time zones, import the timezone package and set the location option to your location…By default, Flux uses the UTC time zone.

import "timezone"

option location = timezone.location(name: "America/Los_Angeles")

After setting the location option, the window() and aggregateWindow() functions become location-aware and utilize dynamic offsets to account for the clock moving forwards or backwards. In this way, you can use either of the following in your query:

from(bucket: "mybucket")
  |> range(start: -1y)
  |> filter(fn: ...)
  |> aggregateWindow(every: 1mo, fn: mean)

from(bucket: "mybucket")
  |> range(start: -1mo)
  |> filter(fn: ...)
  |> aggregateWindow(every: 1d, fn: mean)

Both of these will always result in the time starting and stopping at midnight in the time zone specified.

When the clock skips forward or moves backwards, the time window will either shrink or stretch to accommodate the change in offset.

For parity, a fixed offset can also be specified in the location option.

import "timezone"

option location = timezone.fixed(offset: -8h)

This sets the time zone with a fixed offset of -8h. This fixed offset works the same as UTC, but midnight will always be 8 hours after midnight in UTC.

In a more complex situation, we might need to mix time zones or only use time zones for a single call to a window function. We can use parameters for that rather than a global option.

import "timezone"

option location = timezone.location(name: "America/Los_Angeles")

from(bucket: "mybucket")
  |> range(start: -1y)
  |> filter(fn: ...)
  |> aggregateWindow(
    every: 1h,
    fn: mean,
    timeSrc: "_start",
    location: timezone.utc, // overrides the global option to use utc
  |> aggregateWindow(every: 1w, fn: max) // global option is used

We hope that this feature will enable many new use cases for processing time series data in Flux.

Related Blog Posts

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top