Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document that naïve datetime objects represent local time #91384

Open
pganssle opened this issue Apr 5, 2022 · 4 comments
Open

Document that naïve datetime objects represent local time #91384

pganssle opened this issue Apr 5, 2022 · 4 comments
Assignees
Labels
3.9 only security fixes 3.10 only security fixes 3.11 only security fixes docs Documentation in the Doc dir type-feature A feature request or enhancement

Comments

@pganssle
Copy link
Member

pganssle commented Apr 5, 2022

BPO 47228
Nosy @abalkin, @pganssle

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = 'https://github.com/pganssle'
closed_at = None
created_at = <Date 2022-04-05.14:04:48.970>
labels = ['3.11', 'type-feature', '3.9', '3.10', 'docs']
title = 'Document that na\xc3\xafve datetime objects represent local time'
updated_at = <Date 2022-04-05.14:04:48.970>
user = 'https://github.com/pganssle'

bugs.python.org fields:

activity = <Date 2022-04-05.14:04:48.970>
actor = 'p-ganssle'
assignee = 'p-ganssle'
closed = False
closed_date = None
closer = None
components = ['Documentation']
creation = <Date 2022-04-05.14:04:48.970>
creator = 'p-ganssle'
dependencies = []
files = []
hgrepos = []
issue_num = 47228
keywords = []
message_count = 1.0
messages = ['416778']
nosy_count = 2.0
nosy_names = ['belopolsky', 'p-ganssle']
pr_nums = []
priority = 'normal'
resolution = None
stage = 'needs patch'
status = 'open'
superseder = None
type = 'enhancement'
url = 'https://bugs.python.org/issue47228'
versions = ['Python 3.9', 'Python 3.10', 'Python 3.11']

@pganssle
Copy link
Member Author

pganssle commented Apr 5, 2022

Currently, the datetime documentation has this to say about naïve datetimes:

A naive object does not contain enough information to unambiguously locate itself relative to other date/time objects. Whether a naive object represents Coordinated Universal Time (UTC), local time, or time in some other timezone is purely up to the program, just like it is up to the program whether a particular number represents metres, miles, or mass. Naive objects are easy to understand and to work with, at the cost of ignoring some aspects of reality.

This was accurate in Python 2.7, but as of Python 3, the picture is a bit more nuanced. .astimezone() and .timestamp() work for naïve datetimes, but they are treated as system local times. It is no longer really appropriate to use a naïve datetime to a datetime in any specific concrete time zone — instead, they should be considered either abstract datetimes for the purposes of calendar calculations, or they should be considered as representing the realization of that abstract datetime in the current system locale. This new behavior is referenced in, for example, the warning in .utcnow(): https://docs.python.org/3.10/library/datetime.html#datetime.datetime.utcnow

We make reference to this in the documentation for .timestamp(): https://docs.python.org/3.10/library/datetime.html#datetime.datetime.timestamp and in .astimezone(): https://docs.python.org/3.10/library/datetime.html#datetime.datetime.astimezone, but the top level explanation makes no reference to it.

I have written a blog post about why this is the case: https://blog.ganssle.io/articles/2022/04/naive-local-datetimes.html and made reference to this behavior in an earlier blog post about utcnow: https://blog.ganssle.io/articles/2019/11/utcnow.html, but I think it would be a good idea to revamp the official documentation to reflect this change in status (12 years or so after the change…)

@pganssle pganssle added 3.9 only security fixes 3.10 only security fixes 3.11 only security fixes labels Apr 5, 2022
@pganssle pganssle self-assigned this Apr 5, 2022
@pganssle pganssle added docs Documentation in the Doc dir type-feature A feature request or enhancement 3.9 only security fixes 3.10 only security fixes 3.11 only security fixes labels Apr 5, 2022
@pganssle pganssle self-assigned this Apr 5, 2022
@pganssle pganssle added docs Documentation in the Doc dir type-feature A feature request or enhancement labels Apr 5, 2022
@ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
@AndersMunch
Copy link

There is any number of "systems" that a naïve datetime can refer to: A database value, something received over the wire or read from a file, or indeed, the local time of the computer on which the program is currently running. You cannot know which point in time it refers to or what its timezone is without some sort of out-of-band knowledge. That .astimezone and .timestamp take a guess and use the local time interpretation is not an example to be followed.

The underlying problem is that datetime.now() forgets the origin of the date/time, making it impossible tell the difference between a local time (such as the what now()) returns, and a datetime.datetime() constructed from an external source. I don't think the meaning of naïve datetimes should be changed without a plan for how to address the underlying problem.

@pganssle
Copy link
Member Author

@AndersMunch I'm not raising this issue to suggest that we change anything about the nature of datetime, but rather that we document what is currently true about datetime. I do not see any way to fix this "in place" and for a data structure as common and fundamental as datetime I don't think we're likely to be able to migrate to a replacement.

As I noted in my article on the subject, the design that we already have is probably about as good as we can do. We cannot have datetime.now() "remember" that it is a system time because datetime's semantics preclude the creation of a safe "system local time" tzinfo. We should document that the APIs are designed with this in mind — at least it will give people a better mental model for how datetime is going to perform in various situations.

@AndersMunch
Copy link

@pganssle but it isn't currently true. For example, DBAPI implementations[1] return naïve datetime's that are not in the current program local time. What they mean depends on context and convention, and quite often that convention will be that database times are UTC, or database server time, or some stipulated "server local time". The one thing it won't be is the system time of whatever database client that is currently connecting, because that would be broken. Naïve datetime's, as found in the wild, don't obey your mental model.

Take care that you distinguish between times that are local in the sense of being an imprecise notation for a single precise point in time, like datetime.now(), and times that are local in the sense of corresponding to multiple different points in time as interpreted by viewpoint: An example of the latter is if I say to you, "you should get up at 5am[2] and see the sunrise" -- in this context 5am means 05:00+02:00 to me, but it might mean 05:00-06:00 to you, and neither is more right than the other. "5am" is not a point in time itself, it's a recipe for how to compute a point in time given additional information. If you declare naïve datetime to be system time then you've outlawed this use.

[1] Not all of them, databases these days have datatypes with timezone information, but I've mostly encountered the other form.
[2] Using "5am" as short for datetime.datetime(2022, 4, 29, 5, 0).

@abalkin abalkin self-assigned this Feb 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.9 only security fixes 3.10 only security fixes 3.11 only security fixes docs Documentation in the Doc dir type-feature A feature request or enhancement
Projects
Development

No branches or pull requests

3 participants