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

Possible bug in datetime utc #88829

Closed
gabhcosta mannequin opened this issue Jul 17, 2021 · 8 comments
Closed

Possible bug in datetime utc #88829

gabhcosta mannequin opened this issue Jul 17, 2021 · 8 comments
Labels
3.9 only security fixes stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@gabhcosta
Copy link
Mannequin

gabhcosta mannequin commented Jul 17, 2021

BPO 44663
Nosy @tim-one, @vedgar, @cryvate, @primal100, @gabhcosta

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 = None
closed_at = None
created_at = <Date 2021-07-17.21:20:17.951>
labels = ['type-bug', 'library', '3.9']
title = 'Possible bug in datetime utc'
updated_at = <Date 2021-07-20.13:31:15.567>
user = 'https://github.com/gabhcosta'

bugs.python.org fields:

activity = <Date 2021-07-20.13:31:15.567>
actor = 'petr.viktorin'
assignee = 'none'
closed = False
closed_date = None
closer = None
components = ['Library (Lib)']
creation = <Date 2021-07-17.21:20:17.951>
creator = 'gabhcosta'
dependencies = []
files = []
hgrepos = []
issue_num = 44663
keywords = []
message_count = 6.0
messages = ['397733', '397734', '397736', '397740', '397753', '397769']
nosy_count = 5.0
nosy_names = ['tim.peters', 'veky', 'cryvate', 'primal', 'gabhcosta']
pr_nums = []
priority = 'normal'
resolution = None
stage = None
status = 'open'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue44663'
versions = ['Python 3.9']

@gabhcosta
Copy link
Mannequin Author

gabhcosta mannequin commented Jul 17, 2021

>>> datetime.now(timezone.utc).timestamp()
1626556067.054988
>>> datetime.utcnow().timestamp()
1626566875.174921

Should there be a difference between the two modes?

@gabhcosta gabhcosta mannequin added topic-C-API 3.9 only security fixes type-bug An unexpected behavior, bug, or error labels Jul 17, 2021
@Cryvate
Copy link
Mannequin

Cryvate mannequin commented Jul 17, 2021

I don't seem to be able to reproduce this by running this one-liner:

from datetime import datetime, timezone; print(datetime.now(timezone.utc).timestamp()); print(datetime.u
tcnow().timestamp());

on 3.9.5. How did you achieve this? It looks like the difference one would expect from (fast) human input).

@tim-one
Copy link
Member

tim-one commented Jul 17, 2021

It looks like the difference one would expect from (fast) human input)

Nope, the timestamps in the original report are about 3 hours apart (10808+ seconds).

Reports like these are often much clearer if they state the timezone of the system they're running on.

Plausible here: as the docs say, utcnow() returns a naive datetime - no timezone info is attached.

But .timestamp():

"""
Naive datetime instances are assumed to represent local time
"""

So I _expect_ the results to differ unless the box this is running on uses UTC as its local time.

On my box, in native timezone CDT, the two ways are 5 hours apart, which is indeed CDT's offset from UTC.

@vedgar
Copy link
Mannequin

vedgar mannequin commented Jul 18, 2021

Would it be possible to change .utcnow to now return a datetime annotated with UTC "timezone"? After all, now we have timezone-aware datetimes and the convention that naive means local, this behavior might even be considered a bug.

@primal100
Copy link
Mannequin

primal100 mannequin commented Jul 18, 2021

The difference between the two is the difference between your local time and utc.

datetime.now(timezone.utc)

This returns the current time in utc and is timezone aware. So the timestamp can figure out the seconds since epoch taking into account the timezone.

datetime.utcnow()

Returns the current utc time but is not timezone aware. When timestamp method is run, it is interpreted as a local timestamp.

This is explained in the docs but perhaps it should be made clearer that
datetime.utcnow().timestamp() is incorrect and would cause bugs.

I'm not sure about changing the behaviour of utcnow to return a timezone-aware dt as is it could cause hard to detect bugs in existing code. But I did have issues recently where I was using utcnow until I went back and read the docs and changed to datetime.now(timezone.utc). So it's probably a common trap to fall into.

From the docs:

"
Naive datetime instances are assumed to represent local time #

Note There is no method to obtain the POSIX timestamp directly from a naive datetime instance representing UTC time. If your application uses this convention and your system timezone is not set to UTC, you can obtain the POSIX timestamp by supplying tzinfo=timezone.utc:
timestamp = dt.replace(tzinfo=timezone.utc).timestamp()
or by calculating the timestamp directly:

timestamp = (dt - datetime(1970, 1, 1)) / timedelta(seconds=1)"

Warning Because naive datetime objects are treated by many datetime methods as local times, it is preferred to use aware datetimes to represent times in UTC. As such, the recommended way to create an object representing the current time in UTC is by calling datetime.now(timezone.utc).
"

@tim-one
Copy link
Member

tim-one commented Jul 19, 2021

If you want to pursue changing what utcnow() does, python-ideas or python-dev would probably need to be involved. Backward-incompatible changes are very hard sells.

As Paul Ganssle noted here,

https://blog.ganssle.io/articles/2019/11/utcnow.html

in Python 2, naïve datetimes generally did _not_ get treated as "being in local time", ever. They refused to pretend they had any opinion about time zone, and operations like .timestamp() (just "like", because .timestamp() didn't exist in Python 2) raised an exception when applied to a naïve datetime.

Which, IMO, Python 3 should have stuck with. "Naïve time" was never intended to be a synonym for "local time" - or for UTC time - or for any other timezone-aware notion of time.

But as Paul also said, if Python 2 had concrete tzinfo classes to begin with, it's a pretty safe bet utcnow() would never have existed.

@encukou encukou added stdlib Python modules in the Lib dir and removed topic-C-API labels Jul 20, 2021
@ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
SmartManoj added a commit to SmartManoj/cpython that referenced this issue Apr 19, 2022
@SmartManoj
Copy link

SmartManoj commented Apr 20, 2022

@pganssle How about deprecate utcnow() now?

@iritkatriel
Copy link
Member

It's been deprecated, so closing this as out of date.

>>> datetime.datetime.utcnow()
<stdin>-5:1: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
datetime.datetime(2023, 10, 27, 17, 56, 54, 484802)

@iritkatriel iritkatriel closed this as not planned Won't fix, can't repro, duplicate, stale Oct 27, 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 stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
Projects
Archived in project
Development

No branches or pull requests

4 participants