Python datetime object show wrong timezone offset
See: http://bytes.com/topic/python/answers/676275-pytz-giving-incorrect-offset-timezone
In the comments, someone proposes to use tzinfo.localize()
instead of the datetime
constructor, which does the trick.
>>> tz = timezone('Asia/Kolkata')
>>> dt = tz.localize(datetime.datetime(2011, 6, 20, 0, 0, 0, 0))
>>> dt
datetime.datetime(2011, 6, 20, 0, 0, tzinfo=<DstTzInfo 'Asia/Kolkata' IST+5:30:00 STD>)
UPDATE: Actually, the official pytz website states that you should always use localize
or astimezone
instead of passing a timezone object to datetime.datetime
.
Python timezone offset wrong?
Instead of assigning the tzinfo
parameter, use the localize
method from pytz.
tz = get_localzone()
date = tz.localize(datetime(2015, 6, 17, 14, 58, 45))
This is discussed prominently in the pytz documentation, starting with the the first "Note" box, and in the very first code sample.
It's also shown in the tzlocal documentation, which is where (I assume) your get_localzone()
method is coming from.
FYI, the -05:51
offset comes from the original LMT value of the America/Chicago
time zone, which is -05:50:36
and is assumed to have been in use way back in 1883 as shown here. It's rounded to the nearest minute, giving the -05:51
LMT value in Python. You are seeing that offset because the localize method wasn't called, so pytz is just using the first offset known to that time zone's entry.
creating a timezone aware datetime object returns a wrong timezone
It is mentioned in the docs that constructing datetime objects doesn't work this way.
You are supposed to do this:
from datetime import datetime
from pytz import timezone
eastern = timezone('US/Eastern')
obj = eastern.localize(datetime(2020, 7, 1, 9, 30))
>>> obj
datetime.datetime(2020, 7, 1, 9, 30, tzinfo=<DstTzInfo 'US/Eastern' EDT-1 day, 20:00:00 DST>)
>>> print(obj)
2020-07-01 09:30:00-04:00
isoformat function of datetime module in python returns incorrect offset
It's almost always wrong to just tack on a pytz instance for the tzinfo when creating a datetime. The correct way to convert a naive datetime into a timezone aware instance using pytz is with the zone's localize method:
zone.localize(dt)
Output for your case:
>>> print(timezone.localize(zoned_time_stamp))
2017-06-01 05:30:00+05:30
It's quite clearly documented that passing a pytz instance in tzinfo is not a supported way of creating a localized datetime. However, that's also such a commonly seen mistake in Python code - guess many users don't read the docs!
To understand why the incorrect approach showed what it did (weird +05:53
offset), refer to pytz: The Fastest Footgun in the West by Paul Ganssle.
datetuil results in wrong utc offset when using lower case
The dateutil library, by default, diverges from POSIX-style time zones, which "use an inverted offset format, so normally GMT+3 would be parsed as an offset 3 hours behind GMT. The tzstr time zone object will parse this as an offset 3 hours ahead of GMT" (dateutil documentation on dateutil.tz.tzstr()).
The library determines when to invert the offset by checking if your timezone abbreviation is either "UTC" or "GMT" (case sensitive), then multiplies the offset by -1. Because the check is case sensitive, the offset for "UTC-6" does properly get offset to -0600 but "utc-6" does not (tzstr source code).
# Here we break the compatibility with the TZ variable handling.
# GMT-3 actually *means* the timezone -3.
if res.stdabbr in ("GMT", "UTC") and not posix_offset:
res.stdoffset *= -1
Regardless of if this was an intentional decision, with the current tzstr implementation, you should uppercase your timezone strings before passing them in to gettz()
.
pytz giving wrong timezone offset for 'Africa/Khartoum'
I cannot reproduce the example for datetime.datetime.now
. pytz
also shows the correct UTC offset change in 2017 for the timezone 'Africa/Khartoum'. However, you need to use the localize
method (see e.g. here).
import datetime
import pytz
tz = pytz.timezone('Africa/Khartoum')
# correct UTC offset for "now":
tz_offset = tz.localize(datetime.datetime.now()).strftime('%z')
print(tz_offset)
# +0200
# also correct UTC offset around 1st Nov 2017:
tz_offset = tz.localize(datetime.datetime(2017,10,31)).strftime('%z')
print(tz_offset)
# +0300
tz_offset = tz.localize(datetime.datetime(2017,11,1)).strftime('%z')
print(tz_offset)
# +0200
If you don't localize
, you only get the local mean time. With dateutil
, you would not have to localize and could implement the timezone directly:
import dateutil
tz = dateutil.tz.gettz('Africa/Khartoum')
tz_offset = datetime.datetime(2017,10,31, tzinfo=tz).strftime('%z')
print(tz_offset)
# +0300
tz_offset = datetime.datetime(2017,11,1, tzinfo=tz).strftime('%z')
print(tz_offset)
# +0200
Related Topics
Python's JSON Module, Converts Int Dictionary Keys to Strings
Standard Way to Embed Version into Python Package
Getting One Value from a Tuple
Python Postgres Psycopg2 Threadedconnectionpool Exhausted
How to Convert an Array of Strings to an Array of Floats in Numpy
Comparing Boolean and Int Using Isinstance
What Is the Most Pythonic Way to Check If an Object Is a Number
Add Params to Given Url in Python
Solving "Dll Load Failed: %1 Is Not a Valid Win32 Application." for Pygame
Can Existing Virtualenv Be Upgraded Gracefully
How to Use Brew Installed Python as the Default Python
How to Convert a Numpy Array to Pil Image Applying Matplotlib Colormap
Is There a "Not Equal" Operator in Python
How to Plot Nan Values as a Special Color with Imshow in Matplotlib
How to Do Assignments in a List Comprehension
Can't Install New Packages for Python (Python 3.9.0, Windows 10)