On 9/18/2012 7:04 PM, Christopher Nelson wrote:
>>> If I want to do:
>>>
>>>   d = datetime.now()
>>>   cursor.execute("INSERT INTO mytable VALUES", somefunc(d))
>>>
>>> what is `somefunc()`
>>>
>>
>> Well, I think you're looking for to_utimestamp:
>>
>> http://www.edgewall.org/docs/branches-1.0-stable/html/api/trac_util_datefmt.html#trac.util.datefmt.to_utimestamp
> 
> I'm seeing:
> 
>   File 
> "/usr/local/lib/python2.6/dist-packages/Trac-0.11.6-py2.6.egg/trac/util/datefmt.py",
> line 69, in to_utimestamp
>     diff = dt - _epoc
>  TypeError: can't subtract offset-naive and offset-aware datetimes
> 
> No doubt I'm passing a bad argument but the document you pointed to
> doesn't indicate if the argument should be offset-naive or
> offset-aware.
> 

You're right, this is not yet documented.

As an aside, when playing on the command line with the datefmt
utilities, I found some surprising differences between our FixedOffset
tzinfo class and the tzinfo classes from pytz: I expected the
"Europe/Paris" timezone from pytz to be the same as our "GMT +2:00"
(when DST is active that is, otherwise GMT +1), but they are not...

>>> from trac.util.datefmt import *
>>> paris = timezone("Europe/Paris")
>>> gmt02 = timezone("GMT +2:00")
>>> (paris, gmt02)
(<DstTzInfo 'Europe/Paris' PMT+0:09:00 STD>, <FixedOffset "GMT +2:00"
2:00:00>)

I have no idea why that DstTzInfo instance shows "PMT+0:09:00", but OK.

First we start by using "naive" datetime objects.

>>> from datetime import datetime
>>> d_naive = datetime.now()
>>> d_paris = to_datetime(d_naive, paris)
>>> d_gmt02 = to_datetime(d_naive, gmt02)

Now if we try to use to_utimestamp() on these datetime objects, we'll
get different values!

>>> to_utimestamp(d_paris)
1347999789289000L
>>> to_utimestamp(d_gmt02)
1347993129289000L

??

But even when comparing directly those datetime objects, we see they're
not the same:

>>> d_paris - d_gmt02
datetime.timedelta(0, 6660)

!? 111 minutes... At first I had no idea what this corresponded to.

The Python docs
(http://docs.python.org/library/datetime.html#datetime-objects) helped a
bit here: "Subtraction of a datetime from a datetime ... If both are
aware and have different tzinfo attributes, a-b acts as if a and b were
first converted to naive UTC datetimes first. The result is ..." (in our
example:)

>>> (d_paris.replace(tzinfo=None) - d_paris.utcoffset()) -
(d_gmt02.replace(tzinfo=None) - d_gmt02.utcoffset())
datetime.timedelta(0, 6660)

And this helps to pinpoint the cause:

>>> d_gmt02.utcoffset()
datetime.timedelta(0, 7200)

(correct, 2 hours)

>>> d_paris.utcoffset()
datetime.timedelta(0, 540)

Ahem, 9 minutes... (remember the PMT+0:09:00 above?)

Googling a bit reveals a similar "surprise" for someone else, a few
years ago:

  http://marc.info/?l=zope3-dev&m=115384670611141&w=2

  The answer was: "Read pytz/README.txt.  You're not supposed to pass
tzinfo to datetime."

Ok, so it really look like we should find an alternative to the
t.replace(tzinfo=tzinfo) we do in to_datetime() when t is a "naive"
datetime, because if we specify there a timezone from pytz, we'll get
non-sensical datetime objects.

If we start with "aware" datetime objects (bootstrapping the tzinfo with
one of our own FixedOffset instance), it indeed works as expected.

>>> d_utc = d_naive.replace(tzinfo=utc)
>>> du_paris = to_datetime(d_utc, paris)
>>> du_gmt02 = to_datetime(d_utc, gmt02)

Then:

>>> du_paris - du_gmt02
datetime.timedelta(0)

Better!

Looks like in Trac we're mostly using "aware" datetime objects anyway,
like when retrieving dates from the database (from_utimestamp(usecs)) or
from the user (user_time(...)), or the current date (datetime.now(utc)),
so that this problem was not apparent. Still, the docs need to be
clarified about the "naive"/"aware" situation and to_datetime() should
be fixed.

-- Christian

-- 
You received this message because you are subscribed to the Google Groups "Trac 
Development" group.
To post to this group, send email to trac-dev@googlegroups.com.
To unsubscribe from this group, send email to 
trac-dev+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/trac-dev?hl=en.

Reply via email to