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