Skip to content

[Bug]: Redundant month in ConciseDateFormatter offset text when it displays days and months #24982

Closed as not planned

Description

@persep

Bug summary

When you make a plot with the ConciseDateFormatter that shows on the x axis days and months the offset_string also shows the month (with the year) which I think is redundant because you only need the year

Code for reproduction

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import datetime

fig, ax = plt.subplots()

d1 = datetime.datetime(1997, 1, 1)
d2 = d1 + datetime.timedelta(weeks=520)

locator = mdates.AutoDateLocator()
formatter = mdates.ConciseDateFormatter(locator)
ax.xaxis.set_major_locator(locator)
ax.xaxis.set_major_formatter(formatter)

ax.plot([d1, d2], [0, 0])

ax.set_xlim(d1, d1 + datetime.timedelta(weeks=3))
ax.set_xlim(d1 + datetime.timedelta(weeks=1),
                d1 + datetime.timedelta(weeks=10))

plt.show()

Actual outcome

image

Expected outcome

image

Additional information

When the ConciseDateFormatter was proposed here you can see the same expected behavior:

image

Operating system

Ubuntu 22.04.1 LTS

Matplotlib Version

3.6.2

Matplotlib Backend

agg

Python version

3.10.6

Jupyter version

No response

Installation

pip

Activity

  1. rcomer commented on Jan 15, 2023

    @rcomer
    Member

    According to the milestone, the ConciseDateFormatter went in at v3.1, and the example in the v3.1 gallery shows “2005-Apr” on the offset even though “Apr” is also an axes tick lebel. So I think it has always been this way.
    https://matplotlib.org/3.1.0/gallery/ticks_and_spines/date_concise_formatter.html#sphx-glr-gallery-ticks-and-spines-date-concise-formatter-py

  2. jklymak commented on Jan 15, 2023

    @jklymak
    Member

    This is expected behaviour - if you had another month in your date range, I think it would change to just showing the year. If you want to change the formats for the different levels there is an offset_formats kwarg to ConciseFormatter, however, I think there are cases in this level where you would want the month to show up as well, so it probably should stay the same. If you want, you can also manually change the offset text ax.xaxis.offsetText.set_string('2009').

    It would be hard to argue that we should change the default, because that would require a whole deprecation cycle, which is difficult for kwargs, and I'd say not worth the pain in this case.

  3. oscargus commented on Jan 15, 2023

    @oscargus
    Member

    I contemplated this when working on #22871

    There a special casing was added for the year and I was thinking about the other cases as well. IIRC it really comes down to what the format strings include and if the first day of the month is hit or not. Although I agree that conceptually, the month should not be in your example, one would simply need another formatter for that, as combining modifiable static formatting and dynamic adaptation of the formatting is not really possible (either we always guess or never guess, sort of, the current solution never guesses).

    I think that another formatter that prints the ticks at a suitable level and then print all remaining date information in the offset, as long as it is not already in the ticks would be doable though, possibly with an argument for "highest" level to be shown in the offset.

    (Finally, one could question if it actually should be Mar in the example. It seems like maybe Jan is a more natural choice for offset?)

  4. persep commented on Jan 15, 2023

    @persep
    Author

    This is expected behaviour - if you had another month in your date range, I think it would change to just showing the year.

    The month and year offset always shows up no matter how many months and days you have like in the first image I posted

  5. jklymak commented on Jan 15, 2023

    @jklymak
    Member

    Again, this is not a bug, just a disagreement about what the defaults should be. Changing the defaults is a breaking API change, so there would have to be a pretty strong reason to do that song and dance. We did go back and forth a fair bit on what the default labels should be and arrived at this as reasonable.

  6. persep commented on Jan 16, 2023

    @persep
    Author

    You can't use the offset_formats argument because the level 2 is used for formatting days and months, and only days, So if I use
    offset_formats=['', '%Y', '%Y', '%Y-%b-%d', '%Y-%b-%d', '%Y-%b-%d %H:%M']
    when plotting days and months the offset will be the year offset_formats[2] which is ok.
    But when you plot days you only get the year when you really need '%Y-%b'.
    The way to solve this would be that if there is a month in the axis then to use %Y and if there isn't any month in the axis to use %Y-%b.
    I think you need one more level to use it this way or a way to detect months, I'm not very good at understanding the matplotlib code.
    But if you all think there is no need to change the code then feel free to close this issue.

  7. oscargus commented on Jan 16, 2023

    @oscargus
    Member

    The thing is that you would need to do that at every level. If you plot hours, then you will need to check a day is printed and in that case select a different string. It is not possible to implement it like that, just an alternative_offset_format. But then there will be a case where not only the day, but the month is plotted and then the month should not be there so a second_alternative_offset_format is required and so on.

    Another example: say that you set the tick format for month as "%Y-%b", then you do not want offset to print year either.

    So either one goes with a static mechanism (as now) or one can write a fully automatic version. (Or a third version that parses the format strings and then removes any format markers from the offset that are printed in the ticks.)

    I think we all agree that there are cases where the current defaults are not ideal in all cases (there are no defaults that are ideal in all cases), but one can change the format as required and there are no "surprises".

    I think this can be kept open as it clearly indicates a need for another formatter that guesses more (and probably is less configurable).

  8. oscargus commented on Jan 16, 2023

    @oscargus
    Member

    Actually, what we can do is to change the logic so that if the zero_formats string is used, the level is changed by one. At least optionally. Not sure that it fully makes sense for all the default value levels, but I guess that is more or less the request.

    (Still it will need a deprecation period if we change the default behavior.)

  9. persep commented on Jan 16, 2023

    @persep
    Author

    Yes I think that might work

  10. github-actions commented on Feb 23, 2026

    @github-actions

    This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!

  11. added
    status: closed as inactiveIssues closed by the "Stale" Github Action. Please comment on any you think should still be open.
    on Mar 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    status: closed as inactiveIssues closed by the "Stale" Github Action. Please comment on any you think should still be open.status: inactiveMarked by the “Stale” Github Actiontopic: date handling

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions