Edgewall Software

Opened 10 years ago

Last modified 9 years ago

#10863 closed defect

fix to_datetime() when given timezone naive datetime input — at Initial Version

Reported by: Christian Boos Owned by:
Priority: normal Milestone: 0.12.5
Component: general Version: 0.12-stable
Severity: normal Keywords: datetime pytz timezone
Cc: Branch:
Release Notes:
API Changes:
Internal Changes:


While looking at some specifics of the trac.util.datefmt.to_datetime function, I discovered that a particular usage pattern is problematic with pytz timezones:

>>> from trac.util.datefmt import *
>>> from datetime import datetime
>>> t = to_datetime(datetime(2012,1,1), timezone("Europe/Paris"))
>>> t.utcoffset()
datetime.timedelta(0, 540)

(from gmessage:trac-dev:V0HeDyfa_pk/5r33UatF3nEJ)

The utcoffset() plays a role when converting a time to the number of ms (to_utimestamp()). Here, it has a value of 9 minutes, which is quite wrong for our purpose.

The workaround is to always specify a timezone aware datetime object to to_datetime, but this is not documented, and shouldn't be necessary either (assuming a timezone naive datetime should actually be the same as a datetime in utc).

The following should

  • trac/util/datefmt.py

    diff --git a/trac/util/datefmt.py b/trac/util/datefmt.py
    index b59a276..d88d6b1 100644
    a b def to_datetime(t, tzinfo=None):  
    6666    elif isinstance(t, datetime):
    6767        if tzinfo is not None:
    6868            if t.tzinfo is None:
    69                 t = t.replace(tzinfo=tzinfo)
     69                t = tzinfo.localize(t)
    7070            else:
    7171                t = tzinfo.normalize(t.astimezone(tzinfo))
    7272        return t

With this change, the t.utcoffset() for the example above would give 3600 seconds, i.e. the one hour we would expect.

Change History (0)

Note: See TracTickets for help on using tickets.