jpayne@68: Pytz Support jpayne@68: ============ jpayne@68: jpayne@68: Allows the pytz package to be used for time zone information. The jpayne@68: advantage of using pytz is that it has a more complete and up to date jpayne@68: time zone and daylight savings time database. jpayne@68: jpayne@68: Usage jpayne@68: ----- jpayne@68: You don't have to do anything special to make it work. jpayne@68: jpayne@68: >>> from DateTime import DateTime, Timezones jpayne@68: >>> d = DateTime('March 11, 2007 US/Eastern') jpayne@68: jpayne@68: Daylight Savings jpayne@68: ---------------- jpayne@68: In 2007 daylight savings time in the US was changed. The Energy Policy jpayne@68: Act of 2005 mandates that DST will start on the second Sunday in March jpayne@68: and end on the first Sunday in November. jpayne@68: jpayne@68: In 2007, the start and stop dates are March 11 and November 4, jpayne@68: respectively. These dates are different from previous DST start and jpayne@68: stop dates. In 2006, the dates were the first Sunday in April (April jpayne@68: 2, 2006) and the last Sunday in October (October 29, 2006). jpayne@68: jpayne@68: Let's make sure that DateTime can deal with this, since the primary jpayne@68: motivation to use pytz for time zone information is the fact that it jpayne@68: is kept up to date with daylight savings changes. jpayne@68: jpayne@68: >>> DateTime('March 11, 2007 US/Eastern').tzoffset() jpayne@68: -18000 jpayne@68: >>> DateTime('March 12, 2007 US/Eastern').tzoffset() jpayne@68: -14400 jpayne@68: >>> DateTime('November 4, 2007 US/Eastern').tzoffset() jpayne@68: -14400 jpayne@68: >>> DateTime('November 5, 2007 US/Eastern').tzoffset() jpayne@68: -18000 jpayne@68: jpayne@68: Let's compare this to 2006. jpayne@68: jpayne@68: >>> DateTime('April 2, 2006 US/Eastern').tzoffset() jpayne@68: -18000 jpayne@68: >>> DateTime('April 3, 2006 US/Eastern').tzoffset() jpayne@68: -14400 jpayne@68: >>> DateTime('October 29, 2006 US/Eastern').tzoffset() jpayne@68: -14400 jpayne@68: >>> DateTime('October 30, 2006 US/Eastern').tzoffset() jpayne@68: -18000 jpayne@68: jpayne@68: Time Zones jpayne@68: --------- jpayne@68: DateTime can use pytz's large database of time zones. Here are some jpayne@68: examples: jpayne@68: jpayne@68: >>> d = DateTime('Pacific/Kwajalein') jpayne@68: >>> d = DateTime('America/Shiprock') jpayne@68: >>> d = DateTime('Africa/Ouagadougou') jpayne@68: jpayne@68: Of course pytz doesn't know about everything. jpayne@68: jpayne@68: >>> from DateTime.interfaces import SyntaxError jpayne@68: >>> try: jpayne@68: ... d = DateTime('July 21, 1969 Moon/Eastern') jpayne@68: ... print('fail') jpayne@68: ... except SyntaxError: jpayne@68: ... print('ok') jpayne@68: ok jpayne@68: jpayne@68: You can still use zone names that DateTime defines that aren't part of jpayne@68: the pytz database. jpayne@68: jpayne@68: >>> d = DateTime('eet') jpayne@68: >>> d = DateTime('iceland') jpayne@68: jpayne@68: These time zones use DateTimes database. So it's preferable to use the jpayne@68: official time zone name. jpayne@68: jpayne@68: One trickiness is that DateTime supports some zone name jpayne@68: abbreviations. Some of these map to pytz names, so these abbreviations jpayne@68: will give you time zone date from pytz. Notable among abbreviations jpayne@68: that work this way are 'est', 'cst', 'mst', and 'pst'. jpayne@68: jpayne@68: Let's verify that 'est' picks up the 2007 daylight savings time changes. jpayne@68: jpayne@68: >>> DateTime('March 11, 2007 est').tzoffset() jpayne@68: -18000 jpayne@68: >>> DateTime('March 12, 2007 est').tzoffset() jpayne@68: -14400 jpayne@68: >>> DateTime('November 4, 2007 est').tzoffset() jpayne@68: -14400 jpayne@68: >>> DateTime('November 5, 2007 est').tzoffset() jpayne@68: -18000 jpayne@68: jpayne@68: You can get a list of time zones supported by calling the Timezones() function. jpayne@68: jpayne@68: >>> Timezones() #doctest: +ELLIPSIS jpayne@68: ['Africa/Abidjan', 'Africa/Accra', 'Africa/Addis_Ababa', ...] jpayne@68: jpayne@68: Note that you can mess with this list without hurting things. jpayne@68: jpayne@68: >>> t = Timezones() jpayne@68: >>> t.remove('US/Eastern') jpayne@68: >>> d = DateTime('US/Eastern') jpayne@68: jpayne@68: jpayne@68: Internal Components jpayne@68: ------------------- jpayne@68: jpayne@68: The following are tests of internal components. jpayne@68: jpayne@68: Cache jpayne@68: ~~~~~ jpayne@68: jpayne@68: The DateTime class uses a new time zone cache. jpayne@68: jpayne@68: >>> from DateTime.DateTime import _TZINFO jpayne@68: >>> _TZINFO #doctest: +ELLIPSIS jpayne@68: jpayne@68: jpayne@68: The cache maps time zone names to time zone instances. jpayne@68: jpayne@68: >>> cache = _TZINFO jpayne@68: >>> tz = cache['GMT+730'] jpayne@68: >>> tz = cache['US/Mountain'] jpayne@68: jpayne@68: The cache also must provide a few attributes for use by the DateTime jpayne@68: class. jpayne@68: jpayne@68: The _zlst attribute is a list of supported time zone names. jpayne@68: jpayne@68: >>> cache._zlst #doctest: +ELLIPSIS jpayne@68: ['Africa/Abidjan'... 'Africa/Accra'... 'IDLE'... 'NZST'... 'NZT'...] jpayne@68: jpayne@68: The _zidx attribute is a list of lower-case and possibly abbreviated jpayne@68: time zone names that can be mapped to official zone names. jpayne@68: jpayne@68: >>> 'australia/yancowinna' in cache._zidx jpayne@68: True jpayne@68: >>> 'europe/isle_of_man' in cache._zidx jpayne@68: True jpayne@68: >>> 'gmt+0500' in cache._zidx jpayne@68: True jpayne@68: jpayne@68: Note that there are more items in _zidx than in _zlst since there are jpayne@68: multiple names for some time zones. jpayne@68: jpayne@68: >>> len(cache._zidx) > len(cache._zlst) jpayne@68: True jpayne@68: jpayne@68: Each entry in _zlst should also be present in _zidx in lower case form. jpayne@68: jpayne@68: >>> for name in cache._zlst: jpayne@68: ... if not name.lower() in cache._zidx: jpayne@68: ... print("Error %s not in _zidx" % name.lower()) jpayne@68: jpayne@68: The _zmap attribute maps the names in _zidx to official names in _zlst. jpayne@68: jpayne@68: >>> cache._zmap['africa/abidjan'] jpayne@68: 'Africa/Abidjan' jpayne@68: >>> cache._zmap['gmt+1'] jpayne@68: 'GMT+1' jpayne@68: >>> cache._zmap['gmt+0100'] jpayne@68: 'GMT+1' jpayne@68: >>> cache._zmap['utc'] jpayne@68: 'UTC' jpayne@68: jpayne@68: Let's make sure that _zmap and _zidx agree. jpayne@68: jpayne@68: >>> idx = set(cache._zidx) jpayne@68: >>> keys = set(cache._zmap.keys()) jpayne@68: >>> idx == keys jpayne@68: True jpayne@68: jpayne@68: Timezone objects jpayne@68: ~~~~~~~~~~~~~~~~ jpayne@68: The timezone instances have only one public method info(). It returns jpayne@68: a tuple of (offset, is_dst, name). The method takes a timestamp, which jpayne@68: is used to determine dst information. jpayne@68: jpayne@68: >>> t1 = DateTime('November 4, 00:00 2007 US/Mountain').timeTime() jpayne@68: >>> t2 = DateTime('November 4, 02:00 2007 US/Mountain').timeTime() jpayne@68: >>> tz.info(t1) jpayne@68: (-21600, 1, 'MDT') jpayne@68: >>> tz.info(t2) jpayne@68: (-25200, 0, 'MST') jpayne@68: jpayne@68: If you don't pass any arguments to info it provides daylight savings jpayne@68: time information as of today. jpayne@68: jpayne@68: >>> tz.info() in ((-21600, 1, 'MDT'), (-25200, 0, 'MST')) jpayne@68: True jpayne@68: