You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
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:
importdatetime# Timezone: UTC-14datetime.datetime.min.timestamp() # ValueError: year 0 is out of rangedatetime.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.
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:
importdatetime# Timezone: UTC-14datetime.datetime.min.timestamp() # ValueError: year 0 is out of rangedatetime.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:
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.
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.
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!
Activity
ntBre commentedon Jul 27, 2026
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
ValueErrorwith code like:seemed severe. But maybe that would be quite unusual code to write in the first place.
pganssle commentedon Jul 27, 2026
I believe this is a bug in CPython, not a deliberate behavior that you should be working around.
datetime.minanddatetime.maxshow up in a lot of buggy behavior because they are boundary conditions and they tend to not get prioritized for fixing because: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.minanddatetime.max.Update default rules for v0.17 (#28786)
ntBre commentedon Sep 23, 2026
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!
Update default rules for v0.17 (#28786)
Update default rules for v0.17 (#28786)
Update default rules for v0.17 (#28786)
Update default rules for v0.17 (#28786)
Update default rules for v0.17 (#28786)