How to add timezone into a naive datetime instance in python

Question:

I’ve got a datetime which has no timezone information. I’m now getting the timezone info and would like to add the timezone into the existed datetime instance, how can I do?

d = datetime.datetime.now()
tz = pytz.timezone('Asia/Taipei')

How to add the timezone info tz into datetime a

Asked By: waitingkuo

||

Answers:

Use tz.localize(d) to localize the instance. From the documentation:

The first is to use the localize() method provided by the pytz library. This is used to localize a naive datetime (datetime with no timezone information):

>>> loc_dt = eastern.localize(datetime(2002, 10, 27, 6, 0, 0))
>>> print(loc_dt.strftime(fmt))
2002-10-27 06:00:00 EST-0500

If you don’t use tz.localize(), but use datetime.replace(), chances are that a historical offset is used instead; tz.localize() will pick the right offset in effect for the given date. The US Eastern timezone DST start and end dates have changed over time, for example.

When you try to localize a datetime value that is ambiguous because it straddles the transition period from summer to winter time or vice-versa, the timezone will be consulted to see if the resulting datetime object should have .dst() return True or False. You can override the default for the timezone with the is_dst keyword argument for .localize():

dt = tz.localize(naive, is_dst=True)

or even switch off the choice altogether by setting is_dst=None. In that case, or in the rare cases there is no default set for a timezone, an ambiguous datetime value would lead to a AmbiguousTimeError exception being raised. The is_dst flag is only consulted for datetime values that are ambiguous and is ignored otherwise.

To go back the other way, turn a timezone-aware object back to a naive object, use .replace(tzinfo=None):

naivedt = awaredt.replace(tzinfo=None)
Answered By: Martijn Pieters

If you know that your original datetime was “measured” in the time zone you are trying to add to it, you could (but probably shouldn’t) use replace rather than localize.

# d = datetime.datetime.now()
# tz = pytz.timezone('Asia/Taipei')
d = d.replace(tzinfo=tz)

I can imagine 2 times when this might make sense (the second one happened to me):

  1. Your server locale is set to the incorrect time zone and you are trying to correct a datetime instance by making it aware of this incorrect timezone (and presumably later localizing it to the “correct” time zone so the values of now() match up to other times you are comparing it to (your watch, perhaps)
  2. You want to “tag” a time instance (NOT a datetime) with a time zone (tzinfo) attribute so that attribute can be used later to form a full datetime instance.
Answered By: hobs
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.