How to format dates on a time-series axis in Matplotlib (with Code)
The Short Answer (TL;DR)
Give the axis an AutoDateLocator and a ConciseDateFormatter that uses the same locator. Plot datetime values directly and set the display timezone explicitly when the data represent timed events.
import datetime as dt, matplotlib.pyplot as plt, matplotlib.dates as mdates
fig, ax = plt.subplots(); ax.plot([dt.datetime(2026, 1, 1, tzinfo=dt.timezone.utc) + dt.timedelta(days=i) for i in range(8)], range(8))
locator = mdates.AutoDateLocator(tz=dt.timezone.utc); ax.xaxis.set_major_locator(locator); ax.xaxis.set_major_formatter(mdates.ConciseDateFormatter(locator, tz=dt.timezone.utc))
Detailed Implementation
This example uses synthetic data and does not need a network connection. Install the recorded package versions in a separate Python environment before running it.
python -m pip install numpy==2.5.4 pandas==3.0.6 matplotlib==3.11.2 seaborn==0.13.2
import datetime as dt
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
utc = dt.timezone.utc
dates = [dt.datetime(2026, 1, 25, tzinfo=utc) + dt.timedelta(days=i)
for i in range(18)]
response = np.array([4, 5, 4, 6, 7, 6, 8, 7, 9, 8, 10, 9, 11, 10, 12, 11, 13, 12])
fig, ax = plt.subplots(figsize=(7.0, 3.6), layout="constrained")
ax.plot(dates, response, marker="o", color="#176b87")
locator = mdates.AutoDateLocator(tz=utc, minticks=4, maxticks=7)
formatter = mdates.ConciseDateFormatter(locator, tz=utc)
ax.xaxis.set_major_locator(locator)
ax.xaxis.set_major_formatter(formatter)
ax.set(xlabel="Observation date (UTC)", ylabel="Synthetic response",
title="Daily measurements across a month boundary")
ax.grid(axis="y", alpha=0.25)
fig.savefig("formatted-date-axis.png", dpi=160)
plt.show()
The saved chart shows eighteen daily observations spanning January and February, with compact date tick labels and an explicit UTC axis label.
Why use a locator and formatter together?
The locator chooses tick positions. The formatter chooses their text. Passing the same locator to ConciseDateFormatter lets labels share date context without manually replacing tick strings.
Should dates be converted to strings?
Keep datetime values for plotting. Strings can be treated as categories, so unequal elapsed times may appear equally spaced. Formatting tick text does not change the underlying observation times.
Which timezone does the chart show?
This example uses timezone-aware UTC datetimes and UTC labels. Choose the timezone that matches the intended interpretation; local daylight-saving transitions can make a calendar day differ from 24 elapsed hours.
Mathematical Context
Matplotlib represents dates as elapsed days relative to its configured epoch. A difference of 1 in the numeric coordinate is 24 elapsed hours; 0.25 is six hours. In this UTC example adjacent observations differ by one day. Tick formatting changes the displayed labels while preserving the numerical positions and spacing.
\[ \Delta t_{\mathrm{hours}}=24\,\Delta t_{\mathrm{days}} \]
Reproducibility
Executed with Python 3.12.14; numpy 2.5.4, pandas 3.0.6, matplotlib 3.11.2, seaborn 0.13.2. Automated checks confirm the stated output properties.