This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: email.utils.formatdate function does not handle timezones correctly.
Type: behavior Stage:
Components: Library (Lib) Versions: Python 3.1, Python 3.2, Python 3.3, Python 3.4, Python 2.7, Python 2.6
process
Status: closed Resolution: duplicate
Dependencies: Superseder: datetime-RFC2822 roundtripping
View: 665194
Assigned To: Nosy List: Vitja.Makarov, burak.arslan, izmmisha, petri.lehtinen, r.david.murray
Priority: normal Keywords:

Created on 2011-10-28 10:26 by burak.arslan, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
test_formatdate.py burak.arslan, 2011-10-28 10:26 small snippet to illustrate the problem
test_tz.py Vitja.Makarov, 2011-11-03 18:38 Test timezone switch
Messages (8)
msg146551 - (view) Author: Burak Arslan (burak.arslan) Date: 2011-10-28 10:26
There's an issue with email.utils.formatdate function, illustrated here: https://gist.github.com/1321994

for reference i'm on Europe/Istanbul timezone, which is +03:00 because of DST at the time of this writing.

I'm on stable Python 2.7.2 on gentoo linux. 

When I run the attached script, I get:

    Fri, 28 Oct 2011 07:56:14 -0000
    datetime.datetime(2011, 10, 28, 9, 56, 14, 945831, tzinfo=<UTC>)

when the local time is 12:56. so the second line is correct and first one is not.

let me know if you need any more information.
thanks for your attention.
msg146554 - (view) Author: Burak Arslan (burak.arslan) Date: 2011-10-28 12:06
turns out timetuple was not passing timezone information. the correct way of converting a datetime.datetime object to a correct rfc-2822 compliant date string seems to be:

email.utils.formatdate(time.mktime(a.utctimetuple()) + 1e-6 * a.microsecond - time.timezone)

what a mess. if the above is indeed the right way to do this, is it possible to add the following function to the email.utils module?

def formatdatetime(dt_object):
    return email.utils.formatdate(time.mktime(dt_object.utctimetuple()) + 1e-6 * a.microsecond - time.timezone)

this works for datetime instances both with and without time zone information.

ps: i updated the code in the github link but not here.
msg146839 - (view) Author: Mikhail I. Izmestev (izmmisha) Date: 2011-11-02 14:27
I have strange behavior too:

im@cgt-serv ~ $ python
Python 2.6.6 (r266:84292, Feb 28 2011, 09:01:15)
[GCC 4.3.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from email.Utils import formatdate
>>> import time
>>> time.strftime("%a, %d %b %Y %T %z")
'Wed, 02 Nov 2011 18:21:08 +0400'
>>> formatdate(localtime=True)
'Wed, 02 Nov 2011 18:21:28 +0300'
>>>
msg146959 - (view) Author: Vitja Makarov (Vitja.Makarov) Date: 2011-11-03 18:38
We have the same issue in Russia (MSK timezone). It seems to be related to recent changes in timezone info.

It looks like time.timezone is calculated incorrectly.

You can test that with attached script:

$ TZ=Europe/Moscow python /tmp/test_tz.py
-10800 -14400

Both values should be the same.
msg147244 - (view) Author: Vitja Makarov (Vitja.Makarov) Date: 2011-11-07 18:19
Perhaps it's better to calculate utc-offset for each timestamp cause we never know what is correct timezone for given time.

That could be done in C:

localtime, utc_offset = time.localtime_ex(t)

Where localtime is the same as returned by localtime() and utc_offset is set to tm.tm_gmtoff.
If tm_gmtoff isn't available on the target platform time.timezone or time.altzone will be used depending on time.daylight.


Here is simple python version, that subtracts gmtime from localtime tuple:

import time

def calculate_utc_offset(t):
    """
    Returns localtime offset for given unix-time `t`
    """
    loco = time.localtime(t)
    utc = time.gmtime(t)
    odd = cmp(loco.tm_year, utc.tm_year) or cmp(loco.tm_yday, utc.tm_yday)
    return (1440 * odd +
            60 * (loco.tm_hour - utc.tm_hour) +
            loco.tm_min - utc.tm_min))
msg147245 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2011-11-07 18:28
Unless I misunderstand your concerns, this is a duplicate of issue 665194.
msg147247 - (view) Author: Vitja Makarov (Vitja.Makarov) Date: 2011-11-07 18:51
I'm not quite sure. The problem is email.utils.formatdate doesn't respect TZ info changes since it uses time.timezone (or time.altzone) for utc offset. 

Btw it seems that issue 665194 should fix the problem.
msg147251 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2011-11-07 19:15
formatdate doesn't know anything about datetimes, so it doesn't make any sense to me to say that it doesn't notice changes in tzinfo.  That's why the fix for issue 665194 introduces a new method for formatting datetimes.
History
Date User Action Args
2022-04-11 14:57:23adminsetgithub: 57493
2011-11-07 19:15:22r.david.murraysetmessages: + msg147251
2011-11-07 18:51:01Vitja.Makarovsetmessages: + msg147247
2011-11-07 18:28:55r.david.murraysetstatus: open -> closed

nosy: + r.david.murray
messages: + msg147245

superseder: datetime-RFC2822 roundtripping
resolution: duplicate
2011-11-07 18:19:16Vitja.Makarovsetmessages: + msg147244
versions: + Python 2.6, Python 3.1, Python 3.2, Python 3.3, Python 3.4
2011-11-03 18:38:47Vitja.Makarovsetfiles: + test_tz.py
nosy: + Vitja.Makarov
messages: + msg146959

2011-11-02 14:27:28izmmishasetnosy: + izmmisha
messages: + msg146839
2011-10-29 17:53:31petri.lehtinensetnosy: + petri.lehtinen
type: behavior
2011-10-28 12:06:34burak.arslansetmessages: + msg146554
2011-10-28 10:26:04burak.arslancreate