When to use datetime.utcnow() or datetime.now(tz=pytz.utc).replace(tzinfo=None)
Asked Answered
W

4

25

I would like to understand when I should be using

datetime.now(tz=pytz.utc).replace(tzinfo=None)

as opposed to simply

datetime.utcnow()

Will the latter not take into account e.g. daylight savings?

Waylon answered 24/2, 2017 at 7:40 Comment(0)
C
20

A lot of how datetime.datetime will work depends on the machine it is run on. The local time and time zone settings of the host machine will determine the output you will get.

If the host machine is in the UTC timezone then there will be no difference between datetime.datetime.now() and datetime.datetime.utcnow().

According to the pytz documentation:

The preferred way of dealing with times is to always work in UTC, converting to localtime only when generating output to be read by humans.

pytz is used for accounting for daylight savings time, and datetime.datetime.utcnow() is used to provide a universal standardised reference point upon which you can calculate daylight savings. datetime.datetime.utcnow() on it's own will not account for daylight savings.

Chough answered 24/2, 2017 at 8:34 Comment(0)
G
8

You should never use datetime.utcnow() as it gives you a naïve timestamp that you can shoot yourself in the foot with. If you really want a naïve timestamp, make it explicit using your first option. now() takes the tz parameter (which you should always supply, to avoid using the host TZ). But utcnow() obviously doesn't provide that. So it is doomed.

For example, let's say you have a UTC timestamp, and you want to convert it to the local time in Mexico City:

my_timestamp.astimezone(pytz.timezone("America/Mexico_City"))

Looks fine, right? Nope, check this out:

>>> datetime.utcnow()
datetime.datetime(2021, 3, 29, 21, 40, 44, 329559)
>>> datetime.utcnow().astimezone(pytz.timezone("America/Mexico_City"))
datetime.datetime(2021, 3, 29, 21, 40, 44, 329559, tzinfo=<DstTzInfo 'America/Mexico_City' CST-1 day, 18:00:00 STD>)

As you can see, astimezone will just tack on the tz if you give it a naïve timestamp, without adjusting the actual time as expected. (if you didn't want to adjust, you'd have used .replace)

It's super confusing, and you don't run into problems like this if you just make sure you have no naïve timestamps. You can have them in your external APIs, if you like, but tack on a timezone when they enter the system.

To summarize: always use datetime.now(tz=some_tz).

Godewyn answered 29/3, 2021 at 21:47 Comment(3)
>>> datetime.datetime.utcnow() datetime.datetime(2022, 10, 28, 14, 20, 36, 193346) >>> datetime.datetime.utcnow().astimezone(pytz.timezone("America/Mexico_City")) datetime.datetime(2022, 10, 28, 9, 21, 10, 49778, tzinfo=<DstTzInfo 'America/Mexico_City' CDT-1 day, 19:00:00 DST>)Betaine
it did adjust for meBetaine
@Betaine I can't reproduce that, which versions of Python and pytz are you using?Godewyn
S
6

To quote Paul Ganssle's article Stop using utcnow and utcfromtimestamp

[Don't] use utcnow() or utcfromtimestamp() simply because it's the wrong abstraction.

[...]

The reason that we cannot simply change utcnow() into an alias for now(timezone.utc) in the standard library is that would change the semantics of how those datetimes are treated by their consumers

IIRC, he contributed quite a bit to cpython (the core of Python) around datetime.

Hence: Don't use datetime.utcnow()

Subjoinder answered 4/2, 2022 at 4:46 Comment(0)
P
1

This has been updated in Python 3.12 and you should only use datetime.datetime.now(datetime.timezone.utc). See here under datetime.

Note that datetime.utcnow() has been deprecated.

Plat answered 2/11, 2023 at 15:38 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.