Skip to content

DTZ rules should not be in the default set #27197

Closed

Description

@pganssle

Summary

In the latest version of ruff, the flake8-datetimez rules were added to the default rule set. As one of the maintainers of datetime in CPython and someone who has been writing about and giving talks about datetimes, I think this is extremely misguided.

I would keep DTZ002 (don't use datetime.datetime.today), DTZ003 and DTZ004 (don't use utc(now|fromtimestamp)), but that is it. DTZ901 (no datetime.min/datetime.max without a timezone) is probably the most bizarre one because it makes approximately zero sense to use a time zone with one of those: there are a bunch of weird edge cases when you do so, and they represent a time ~2000 years before time zones were invented and a time ~8000 years after the latest date where current time zone information is likely to be a good prediction of future offsets.

The main problem with all the other rules is that they fail to take into account that naïve time zones are the only real way to represent system local time in the datetime module. It is extremely common to want to work in the system local time zone. Having these rules on by default is going to teach people that you should do some very bad patterns like trying to guess what the system local time zone is, or picking a random time zone like "America/New_York" or something.

I strongly recommend making these rules opt-in.

Activity

  1. ntBre commented on Jul 27, 2026

    @ntBre
    Contributor

    Thank you for the feedback! Do you think rules like DTZ901 are valuable in general, just not as part of the defaults? Not knowing too much about time zones, I guess I took the examples in our docs at face value, and the possibility of causing a ValueError with code like:

    import datetime
    
    # Timezone: UTC-14
    datetime.datetime.min.timestamp()  # ValueError: year 0 is out of range
    datetime.datetime.max.timestamp()  # ValueError: year 10000 is out of range

    seemed severe. But maybe that would be quite unusual code to write in the first place.

  2. pganssle commented on Jul 27, 2026

    @pganssle
    Author

    Thank you for the feedback! Do you think rules like DTZ901 are valuable in general, just not as part of the defaults? Not knowing too much about time zones, I guess I took the examples in our docs at face value, and the possibility of causing a ValueError with code like:

    import datetime
    
    # Timezone: UTC-14
    datetime.datetime.min.timestamp()  # ValueError: year 0 is out of range
    datetime.datetime.max.timestamp()  # ValueError: year 10000 is out of range

    seemed severe. But maybe that would be quite unusual code to write in the first place.

    I believe this is a bug in CPython, not a deliberate behavior that you should be working around. datetime.min and datetime.max show up in a lot of buggy behavior because they are boundary conditions and they tend to not get prioritized for fixing because:

    1. They are not particularly meaningful, they represent, respectively, a backwards extension of a calendar that was not in use at the time and a forward extension of a calendar to a future so far-flung that it is unlikely we'll be using the same calendar system (and even if we are, it basically doesn't make sense to talk about things like what time zone it will be at a given day or even to make plans for a specific day). As such, it's often hard to reason about what the behavior of some edge case "should" be, because they aren't representing anything people care about.
    2. No one actually cares about using them, they just want to write bug-free code that properly handles edge cases. That is a laudable goal but it is approximately never going to cause a production outage, so no one ends up demanding it be fixed immediately.

    I don't think linters should generally be making rules just because one path hits an error case and another one doesn't.

    As for whether DTZ901 is ever useful: maybe? To me, the way these DTZ rules can be most useful is when you have a codebase where you know it makes no sense to use system local times for some reason, then you could enable them all. In that case, any situation where you use a naïve datetime is wrong, including presumably datetime.min and datetime.max.

  3. added this to the v0.17 milestone on Jul 29, 2026
  4. linked a pull request that will close this issueUpdate default rules for v0.17 #28786on Sep 22, 2026
  5. added a commit that references this issue on Sep 23, 2026
    6883f4a
  6. ntBre commented on Sep 23, 2026

    @ntBre
    Contributor

    These have been removed for a little while already in preview and will be removed from the stable defaults in the 0.17 release. Thanks again for the feedback!

  7. added 3 commits that reference this issue on Sep 25, 2026
    72c86f0
    ae07b36
    8954e00
  8. added 2 commits that reference this issue on Oct 9, 2026
    18c60dd
    c94a19d
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

    rule-selectionRelated to enabling or disabling rules

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions