[Dev] Timezone-related changes

Grant Baillie grant at osafoundation.org
Thu Mar 2 14:11:50 PST 2006


Hi, all

Here's a summary of various discussions on dealing with time zones  
(especially "floating") in 0.7. In the spirit of PyCon, there is  
actual working Python code in this email, which will hopefully make  
things clearer. In the spirit of being backward, I'm starting out  
with the proposals of how to use timezones, and ending with the  
motivation behind doing things this way).

FWIW, the PyICU-level work has already been done by Andi, and I'm  
sitting on a pile of changes that implements the rest in Chandler,  
but it seemed like a good idea to send out the proposed plan of  
action to dev@ beforehand. Let me know if you have comments/ 
recommendations/disagreements.

Guidelines
----------

1. Don't store naive datetimes/times (datetimes or times with a  
tzinfo of None) in the repository. You can still use naive datetimes  
in your code, so long as you don't try to persist them.

[Aside: At some point, we should make the repository reject datetime/ 
time values with a tzinfo of None, similar to other repository type  
checking].

2. The default ICU tzinfo can now be accessed via an attribute rather  
than a classmethod call:

 >>> import datetime, PyICU
 >>> PyICU.ICUtzinfo.default
<ICUtzinfo: US/Pacific>

   (This used to be PyICUtzinfo.getDefault(), which still works for  
now).

3. If you want to create a "floating" datetime/time (i.e. one that in  
0.6 would have had a tzinfo of None), set its tzinfo to the new PyICU  
object PyICU.ICUtzinfo.floating, e.g.


 >>> dt=datetime.datetime(2006, 3, 2, 16, 30,  
tzinfo=PyICU.ICUtzinfo.floating)
 >>> dt
datetime.datetime(2006, 3, 2, 16, 30, tzinfo=<FloatingTZ: US/Pacific>)

   This tzinfo object has the property that it will always perform  
calculations using the default ICU tzinfo (even if that gets changed):

 >>> PyICU.ICUtzinfo.default = PyICU.ICUtzinfo.getInstance("Africa/ 
Johannesburg")
 >>> dt
datetime.datetime(2006, 3, 2, 16, 30, tzinfo=<FloatingTZ: Africa/ 
Johannesburg>)

4. In the not too distant future, we will want to enable having the  
user's default timezone be "floating" (i.e. have a Palm-like timezone- 
free mode): for details, see the following (longish) thread on the  
design list:

<http://lists.osafoundation.org/pipermail/design/2006-January/ 
003758.html>

Note that "the user's default timezone" here means the timezone  
that's used to create new events. For the moment, you get at that  
(persisted) value via the TimeZoneInfo class inside  
osaf.pim.calendar.TimeZone:

 >>> from osaf.pim.calendar.TimeZone import TimeZoneInfo
 >>> from application.schema import _get_nrv
 >>> TimeZoneInfo.get(_get_nrv()) # _get_nrv is the null repository view
<TimeZoneInfo (new): defaultInfo fce1fe34-aa35-11da-88f4-000d9359ec2c>
 >>> _.default
<ICUtzinfo: Africa/Johannesburg>


Motivation
----------

As you may remember, when implementing timezone support in 0.6, there  
was a serious issue with the python datetime API: datetimes/times  
with a tzinfo of None (a.k.a. "naive" datetimes) can't raise a  
TypeError when compared with their non-naive counterparts. Here,  
comparison means use of operators like ==, <, <=, etc, as well as  
built-in python functions like cmp, max, list.sort, etc.

Since we wanted to have events with no timezone (a.k.a. "floating"  
events), the somewhat kludgy strategy I took in implementing timezone  
support was to define a function (the beautiful API  
osaf.calendar.DateTimeUtil.datetimeOp) that would fix up datetimes  
before comparison, if necessary. After that, I trolled though  
chandler code for datetime comparisons that might raise, and replaced  
the offending expressions with calls to datetimeOp().

This strategy is now exposing its clunky roots: For example, sorting  
columns in the summary table means that we would have to define a  
special sort function that called datetimeOp if the attribute being  
sorted on was datetime-valued. In the new scheme of things,  
"floating" datetimes have a non-None tzinfo, so we no longer get a  
TypeErrro during comparisons, and everything is hunky dory. In this  
case, it seems better to lay down rules (to use an authoritarian  
term) that contrain your data, rather than try to erect a creaky  
scaffolding around an undesirable behaviour of Python datetime/time.

--Grant




More information about the Dev mailing list