Date axes turn time-series values into labels that readers can compare without decoding raw timestamps. In Matplotlib, date values are converted through the axis unit system, and the tick locator and formatter control where labels appear and how each date is written.
The object-oriented API keeps the formatting attached to the Axes that owns the data. Plot the datetime sequence normally, set a date locator such as MonthLocator for the tick positions, and set a date formatter such as DateFormatter for the visible label text.
Choose a label pattern that matches the reporting interval. Monthly charts often need abbreviated month and year labels, daily charts may need weekday or day-of-month text, and variable date ranges can use AutoDateLocator with ConciseDateFormatter when manual intervals would make the axis brittle.
from datetime import datetime from pathlib import Path import matplotlib.dates as mdates import matplotlib.pyplot as plt months = [datetime(2026, month, 1) for month in range(1, 13)] tickets_closed = [42, 45, 47, 51, 55, 58, 63, 61, 66, 70, 74, 79] fig, ax = plt.subplots(figsize=(7, 4), layout="constrained") ax.plot(months, tickets_closed, marker="o", linewidth=2) ax.set_title("Support tickets closed by month") ax.set_xlabel("Month closed") ax.set_ylabel("Tickets closed") ax.grid(True, axis="y", alpha=0.3) ax.set_xlim(months[0], months[-1]) locator = mdates.MonthLocator(bymonth=range(1, 13, 2)) formatter = mdates.DateFormatter("%b %Y") ax.xaxis.set_major_locator(locator) ax.xaxis.set_major_formatter(formatter) ax.tick_params(axis="x", rotation=30) fig.canvas.draw() tick_labels = [ label.get_text() for label in ax.get_xticklabels() if label.get_text() ] output = Path("support-tickets-date-axis.png") fig.savefig(output, dpi=160) print("major locator: MonthLocator(bymonth=range(1, 13, 2))") print("major formatter: DateFormatter('%b %Y')") print(f"tick labels: {', '.join(tick_labels)}") print(f"saved: {output}") print(f"bytes: {output.stat().st_size}") plt.close(fig)
MonthLocator selects the tick positions, and DateFormatter applies Python strftime tokens such as %b for abbreviated month and %Y for four-digit year. Use DayLocator with a shorter formatter for daily charts, or AutoDateLocator with ConciseDateFormatter when the date span changes often and the labels should stay compact.
$ python date_axis_format.py
major locator: MonthLocator(bymonth=range(1, 13, 2))
major formatter: DateFormatter('%b %Y')
tick labels: Jan 2026, Mar 2026, May 2026, Jul 2026, Sep 2026, Nov 2026
saved: support-tickets-date-axis.png
bytes: 58348
The byte count can differ by Matplotlib version, font, backend, and DPI. The tick-label line confirms the date formatter produced the intended labels before the image is opened.
The x-axis should show angled labels for Jan 2026, Mar 2026, May 2026, Jul 2026, Sep 2026, and Nov 2026, with enough bottom margin for the labels to remain readable.
Related: How to fix overlapping labels in Matplotlib
$ rm date_axis_format.py support-tickets-date-axis.png