Implicit timezone conversion with altair

Summary

When plotting timeseries data with altair, the timezone appears to be converted from UTC into the browser locale. The underlying data does not contain any timezone information. When an equivalent plot is created in a jupyter notebook, it correctly displays the time as-is, without adjustment.

Steps to reproduce

Run the following and note the difference between the dataframe and the plot (assuming you are not in a UTC+0 timezone)

Code snippet:

import altair as alt
import streamlit as st
import pandas as pd

df = pd.DataFrame({
    'datetime': [pd.to_datetime('2023-06-01 12:00')],
    'value': [10],
})

df

st.altair_chart(
    alt.Chart(df).mark_bar().encode(
    x='datetime', y='value')
)

Expected behavior:

The plot should display the time without timezone adjustment.

Actual behavior:

The plot shows the datetime adjusted to my timezone, incorrectly assuming the underlying data is UTC.

image

Debug info

  • Streamlit version: Streamlit, version 1.23.1
  • Python version: Python 3.10.8
  • OS version: windows 10 20H2 19042.2965
  • Browser version: Chrome canary 116.0.5813.0 or Edge 114.0.1823.37

Requirements file

streamlit==1.23.1
pandas==1.5.2
altair==5.0.1

2 Likes

Hi @bmada
The problem is probably linked to altair charts library. Check their documentation to properly set timezone.
https://altair-viz.github.io/user_guide/times_and_dates.html

I don’t think so, that page says

A standard timezone-agnostic date/time column in a Pandas dataframe will be both interpreted and displayed as local user time

Streamlit appears to be interpreting the datetime in UTC+0 and displaying in local time. If I use altair directly to plot or save the chart to JSON, there is no timezone conversion.

image

{
    "config": {
        "view": {
            "continuousWidth": 300,
            "continuousHeight": 300
        }
    },
    "data": {
        "name": "data-b3b84f14dc0884d5767aa58adbfd187c"
    },
    "mark": {
        "type": "bar"
    },
    "encoding": {
        "x": {
            "field": "datetime",
            "type": "temporal"
        },
        "y": {
            "field": "value",
            "type": "quantitative"
        }
    },
    "$schema": "https://vega.github.io/schema/vega-lite/v5.8.0.json",
    "datasets": {
        "data-b3b84f14dc0884d5767aa58adbfd187c": [
            {
                "datetime": "2023-06-01T12:00:00",
                "value": 10
            }
        ]
    }
}

I am also having graphs that work fine in Jupyter Notebooks but not in Streamlit, also timezone issues.

About to do additional processing in Pandas to format some datetimes for tooltips. The workarounds I am having to do are pretty jank.

1 Like

I am also having the same problem. Works fine in jupyter notebooks but streamlit assumes UTC and converts to local

Did anyone manage to find a successful work around for the problem?

I’m experiencing this issue too.

streamlit==1.26.0
Python 3.9.6

The workaround I’ve been using is to convert the chart to json and plot using st.vega_lite_chart:

import altair as alt
import streamlit as st
import pandas as pd
import json

df = pd.DataFrame({
    'datetime': [pd.to_datetime('2023-06-01 12:00')],
    'value': [10],
})

df

chart = alt.Chart(df).mark_bar().encode(x='datetime', y='value')

st.vega_lite_chart(json.loads(chart.to_json()))

This decision to convert to UTC looks to be intentional; there is a function that does the conversion: https://github.com/streamlit/streamlit/blob/84e4cb390e004da1441f3e5665b2405ecadac8a6/lib/streamlit/elements/arrow_altair.py#L1186-L1197. Doing this silently and differently to altair/vega feels like a bit of an error. Perhaps there should be a parameter to opt out of this conversion?

1 Like