11

The following plot

import matplotlib
f= plt.figure(figsize=(12,4))
ax = f.add_subplot(111)
df.set_index('timestamp')['values'].plot(ax=ax)
ax.xaxis.set_major_locator(matplotlib.dates.HourLocator(interval=1))
ax.xaxis.set_major_formatter(matplotlib.dates.DateFormatter('%I'))
plt.show()

Renders the hour in the wrong zone (GMT) even though I have:

> df['timestamp'][0]
Timestamp('2014-09-02 18:37:00-0400', tz='US/Eastern')

As a matter of fact, if I comment out the line:

ax.xaxis.set_major_formatter(matplotlib.dates.DateFormatter('%I'))

the hour is rendered in the right time zone.

Why?

Amelio Vazquez-Reina
  • 91,494
  • 132
  • 359
  • 564

3 Answers3

17

I think you can have the desired functionality by setting the timezone in rcParams:

import matplotlib
matplotlib.rcParams['timezone'] = 'US/Eastern'

The formatter is timezone aware and will convert the timestamp to your rcParams timezone (which is probably at UTC), while if you don't format it, it will just take the timestamp and ignore the timezone. If I understand correctly.

More reading:

Community
  • 1
  • 1
Sebastian
  • 5,471
  • 5
  • 35
  • 53
  • 5
    Jesus Christ, that was hard to find. Problem: if you use `mdates.DateFormatter`, then it absolutely ignores the timezone set by `plot_date` or `xaxis_date` and whatever you use, unless you use the tz param on it – Daniel F Aug 17 '17 at 06:48
  • ended up here after digging through [documentation for `rrulewrapper`](https://matplotlib.org/3.1.1/_modules/matplotlib/dates.html) (used by Locators) and seeing _rrule does not play nicely with time zones - especially pytz time zones_. Still very frustrating to deal with timezones all this time later. – arturomp Sep 18 '19 at 02:50
8

If you don't want to change rcParams (which seems to be an easy fix), then you can pass the timezone to mdates.DateFormatter.

from dateutil import tz
mdates.DateFormatter('%H:%M', tz=tz.gettz('Europe/Berlin'))

The problem is that mdates.DateFormatter completely ignores everything you set in like plot_date or xaxis_date or whatever you use.

Daniel F
  • 13,684
  • 11
  • 87
  • 116
1

Using pytz

import pytz
import matplotlib.dates as mdates

my_tz = pytz.timezone('Europe/Berlin')
formatter = mdates.DateFormatter('%m-%d %H:%M', tz=my_tz)
Andrea
  • 249
  • 2
  • 7