From: <ef...@us...> - 2010-06-06 20:52:44
|
Revision: 8389 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8389&view=rev Author: efiring Date: 2010-06-06 20:52:36 +0000 (Sun, 06 Jun 2010) Log Message: ----------- [3009273] update pytz to 2010h Modified Paths: -------------- trunk/matplotlib/lib/pytz/__init__.py trunk/matplotlib/lib/pytz/tzfile.py trunk/matplotlib/lib/pytz/tzinfo.py trunk/matplotlib/lib/pytz/zoneinfo/Africa/Cairo trunk/matplotlib/lib/pytz/zoneinfo/Africa/Casablanca trunk/matplotlib/lib/pytz/zoneinfo/Africa/Tunis trunk/matplotlib/lib/pytz/zoneinfo/America/Argentina/Buenos_Aires trunk/matplotlib/lib/pytz/zoneinfo/America/Argentina/Catamarca trunk/matplotlib/lib/pytz/zoneinfo/America/Argentina/ComodRivadavia trunk/matplotlib/lib/pytz/zoneinfo/America/Argentina/Cordoba trunk/matplotlib/lib/pytz/zoneinfo/America/Argentina/Jujuy trunk/matplotlib/lib/pytz/zoneinfo/America/Argentina/La_Rioja trunk/matplotlib/lib/pytz/zoneinfo/America/Argentina/Mendoza trunk/matplotlib/lib/pytz/zoneinfo/America/Argentina/Rio_Gallegos trunk/matplotlib/lib/pytz/zoneinfo/America/Argentina/San_Juan trunk/matplotlib/lib/pytz/zoneinfo/America/Argentina/San_Luis trunk/matplotlib/lib/pytz/zoneinfo/America/Argentina/Tucuman trunk/matplotlib/lib/pytz/zoneinfo/America/Argentina/Ushuaia trunk/matplotlib/lib/pytz/zoneinfo/America/Asuncion trunk/matplotlib/lib/pytz/zoneinfo/America/Buenos_Aires trunk/matplotlib/lib/pytz/zoneinfo/America/Campo_Grande trunk/matplotlib/lib/pytz/zoneinfo/America/Catamarca trunk/matplotlib/lib/pytz/zoneinfo/America/Cordoba trunk/matplotlib/lib/pytz/zoneinfo/America/Cuiaba trunk/matplotlib/lib/pytz/zoneinfo/America/Eirunepe trunk/matplotlib/lib/pytz/zoneinfo/America/Ensenada trunk/matplotlib/lib/pytz/zoneinfo/America/Havana trunk/matplotlib/lib/pytz/zoneinfo/America/Jujuy trunk/matplotlib/lib/pytz/zoneinfo/America/Mendoza trunk/matplotlib/lib/pytz/zoneinfo/America/Porto_Acre trunk/matplotlib/lib/pytz/zoneinfo/America/Resolute trunk/matplotlib/lib/pytz/zoneinfo/America/Rio_Branco trunk/matplotlib/lib/pytz/zoneinfo/America/Rosario trunk/matplotlib/lib/pytz/zoneinfo/America/Santiago trunk/matplotlib/lib/pytz/zoneinfo/America/Sao_Paulo trunk/matplotlib/lib/pytz/zoneinfo/America/Tijuana trunk/matplotlib/lib/pytz/zoneinfo/Antarctica/Casey trunk/matplotlib/lib/pytz/zoneinfo/Antarctica/Davis trunk/matplotlib/lib/pytz/zoneinfo/Antarctica/Mawson trunk/matplotlib/lib/pytz/zoneinfo/Asia/Amman trunk/matplotlib/lib/pytz/zoneinfo/Asia/Anadyr trunk/matplotlib/lib/pytz/zoneinfo/Asia/Dacca trunk/matplotlib/lib/pytz/zoneinfo/Asia/Damascus trunk/matplotlib/lib/pytz/zoneinfo/Asia/Dhaka trunk/matplotlib/lib/pytz/zoneinfo/Asia/Gaza trunk/matplotlib/lib/pytz/zoneinfo/Asia/Hong_Kong trunk/matplotlib/lib/pytz/zoneinfo/Asia/Kamchatka trunk/matplotlib/lib/pytz/zoneinfo/Asia/Karachi trunk/matplotlib/lib/pytz/zoneinfo/Brazil/Acre trunk/matplotlib/lib/pytz/zoneinfo/Brazil/East trunk/matplotlib/lib/pytz/zoneinfo/CET trunk/matplotlib/lib/pytz/zoneinfo/Chile/Continental trunk/matplotlib/lib/pytz/zoneinfo/Chile/EasterIsland trunk/matplotlib/lib/pytz/zoneinfo/Cuba trunk/matplotlib/lib/pytz/zoneinfo/Egypt trunk/matplotlib/lib/pytz/zoneinfo/Europe/Belgrade trunk/matplotlib/lib/pytz/zoneinfo/Europe/Berlin trunk/matplotlib/lib/pytz/zoneinfo/Europe/Budapest trunk/matplotlib/lib/pytz/zoneinfo/Europe/Ljubljana trunk/matplotlib/lib/pytz/zoneinfo/Europe/Podgorica trunk/matplotlib/lib/pytz/zoneinfo/Europe/Samara trunk/matplotlib/lib/pytz/zoneinfo/Europe/Sarajevo trunk/matplotlib/lib/pytz/zoneinfo/Europe/Skopje trunk/matplotlib/lib/pytz/zoneinfo/Europe/Sofia trunk/matplotlib/lib/pytz/zoneinfo/Europe/Zagreb trunk/matplotlib/lib/pytz/zoneinfo/Europe/Zurich trunk/matplotlib/lib/pytz/zoneinfo/Hongkong trunk/matplotlib/lib/pytz/zoneinfo/Indian/Mauritius trunk/matplotlib/lib/pytz/zoneinfo/MET trunk/matplotlib/lib/pytz/zoneinfo/Mexico/BajaNorte trunk/matplotlib/lib/pytz/zoneinfo/Pacific/Apia trunk/matplotlib/lib/pytz/zoneinfo/Pacific/Easter trunk/matplotlib/lib/pytz/zoneinfo/Pacific/Fiji trunk/matplotlib/lib/pytz/zoneinfo/iso3166.tab trunk/matplotlib/lib/pytz/zoneinfo/zone.tab Added Paths: ----------- trunk/matplotlib/lib/pytz/CHANGES.txt trunk/matplotlib/lib/pytz/LICENSE.txt trunk/matplotlib/lib/pytz/README.txt trunk/matplotlib/lib/pytz/tests/ trunk/matplotlib/lib/pytz/tests/test_docs.py trunk/matplotlib/lib/pytz/tests/test_tzinfo.py trunk/matplotlib/lib/pytz/zoneinfo/America/Argentina/Salta trunk/matplotlib/lib/pytz/zoneinfo/America/Matamoros trunk/matplotlib/lib/pytz/zoneinfo/America/Ojinaga trunk/matplotlib/lib/pytz/zoneinfo/America/Santa_Isabel trunk/matplotlib/lib/pytz/zoneinfo/America/Santarem Added: trunk/matplotlib/lib/pytz/CHANGES.txt =================================================================== --- trunk/matplotlib/lib/pytz/CHANGES.txt (rev 0) +++ trunk/matplotlib/lib/pytz/CHANGES.txt 2010-06-06 20:52:36 UTC (rev 8389) @@ -0,0 +1,50 @@ +2004-07-25 + + - Improved localtime handling, and added a localize() method enabling + correct creation of local times. + +2005-02-16 + + - Made available under the Zope Public Licence 2.1 (ZPL) and checked + into the Zope3 project. pytz may now be used and redistributed + under either the original MIT license or the ZPL 2.1. + +2005-05-13 + + - Move UTC into the top level pytz module and provide special + case pickle support for this singleton. + +2005-08-14 + + - Ensure all tzinfo instances are efficiently picklable. + +2005-12-31 + + - Add fixed offset timezone classes required by Zope 3 + - Generate and distribute a PO template file listing all timezone + names. Translations are not yet available. + +2007-03-03 + + - Import work by James Henstridge, making pytz load timezone + information from zic compiled binaries at runtime rather than + processing them into Python classes. + +2007-03-26 + + - Update database to version 2007d + - Fix windows incompatibilities, working around limitations on that + platform. + - Fix 2.3 incompatibilities. Installation now requires distutils. + - Passing an invalid timezone name to timezone() now raises an + UnknownTimezoneError, which is a KeyError subclass for backwards + compatibility. + +2007-03-27 + + - Ensure API can accept Unicode strings (Bug #96957) + +2009-09-29 + + - Fix test_zdump tests and bugs the fixed tests picked up, including + the fix for Bug #427444. Added: trunk/matplotlib/lib/pytz/LICENSE.txt =================================================================== --- trunk/matplotlib/lib/pytz/LICENSE.txt (rev 0) +++ trunk/matplotlib/lib/pytz/LICENSE.txt 2010-06-06 20:52:36 UTC (rev 8389) @@ -0,0 +1,19 @@ +Copyright (c) 2003-2009 Stuart Bishop <st...@st...> + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. Added: trunk/matplotlib/lib/pytz/README.txt =================================================================== --- trunk/matplotlib/lib/pytz/README.txt (rev 0) +++ trunk/matplotlib/lib/pytz/README.txt 2010-06-06 20:52:36 UTC (rev 8389) @@ -0,0 +1,543 @@ +pytz - World Timezone Definitions for Python +============================================ + +:Author: Stuart Bishop <st...@st...> + +Introduction +~~~~~~~~~~~~ + +pytz brings the Olson tz database into Python. This library allows +accurate and cross platform timezone calculations using Python 2.3 +or higher. It also solves the issue of ambiguous times at the end +of daylight savings, which you can read more about in the Python +Library Reference (``datetime.tzinfo``). + +Amost all of the Olson timezones are supported. + +Note that this library differs from the documented Python API for +tzinfo implementations; if you want to create local wallclock +times you need to use the ``localize()`` method documented in this +document. In addition, if you perform date arithmetic on local +times that cross DST boundaries, the results may be in an incorrect +timezone (ie. subtract 1 minute from 2002-10-27 1:00 EST and you get +2002-10-27 0:59 EST instead of the correct 2002-10-27 1:59 EDT). A +``normalize()`` method is provided to correct this. Unfortunatly these +issues cannot be resolved without modifying the Python datetime +implementation. + + +Installation +~~~~~~~~~~~~ + +This package can either be installed from a .egg file using setuptools, +or from the tarball using the standard Python distutils. + +If you are installing from a tarball, run the following command as an +administrative user:: + + python setup.py install + +If you are installing using setuptools, you don't even need to download +anything as the latest version will be downloaded for you +from the Python package index:: + + easy_install --upgrade pytz + +If you already have the .egg file, you can use that too:: + + easy_install pytz-2008g-py2.6.egg + + +Example & Usage +~~~~~~~~~~~~~~~ + +Localized times and date arithmetic +----------------------------------- + +>>> from datetime import datetime, timedelta +>>> from pytz import timezone +>>> import pytz +>>> utc = pytz.utc +>>> utc.zone +'UTC' +>>> eastern = timezone('US/Eastern') +>>> eastern.zone +'US/Eastern' +>>> amsterdam = timezone('Europe/Amsterdam') +>>> fmt = '%Y-%m-%d %H:%M:%S %Z%z' + +This library only supports two ways of building a localized time. The +first is to use the ``localize()`` method provided by the pytz library. +This is used to localize a naive datetime (datetime with no timezone +information): + +>>> loc_dt = eastern.localize(datetime(2002, 10, 27, 6, 0, 0)) +>>> print loc_dt.strftime(fmt) +2002-10-27 06:00:00 EST-0500 + +The second way of building a localized time is by converting an existing +localized time using the standard ``astimezone()`` method: + +>>> ams_dt = loc_dt.astimezone(amsterdam) +>>> ams_dt.strftime(fmt) +'2002-10-27 12:00:00 CET+0100' + +Unfortunately using the tzinfo argument of the standard datetime +constructors ''does not work'' with pytz for many timezones. + +>>> datetime(2002, 10, 27, 12, 0, 0, tzinfo=amsterdam).strftime(fmt) +'2002-10-27 12:00:00 AMT+0020' + +It is safe for timezones without daylight savings trasitions though, such +as UTC: + +>>> datetime(2002, 10, 27, 12, 0, 0, tzinfo=pytz.utc).strftime(fmt) +'2002-10-27 12:00:00 UTC+0000' + +The preferred way of dealing with times is to always work in UTC, +converting to localtime only when generating output to be read +by humans. + +>>> utc_dt = datetime(2002, 10, 27, 6, 0, 0, tzinfo=utc) +>>> loc_dt = utc_dt.astimezone(eastern) +>>> loc_dt.strftime(fmt) +'2002-10-27 01:00:00 EST-0500' + +This library also allows you to do date arithmetic using local +times, although it is more complicated than working in UTC as you +need to use the ``normalize()`` method to handle daylight savings time +and other timezone transitions. In this example, ``loc_dt`` is set +to the instant when daylight savings time ends in the US/Eastern +timezone. + +>>> before = loc_dt - timedelta(minutes=10) +>>> before.strftime(fmt) +'2002-10-27 00:50:00 EST-0500' +>>> eastern.normalize(before).strftime(fmt) +'2002-10-27 01:50:00 EDT-0400' +>>> after = eastern.normalize(before + timedelta(minutes=20)) +>>> after.strftime(fmt) +'2002-10-27 01:10:00 EST-0500' + +Creating localtimes is also tricky, and the reason why working with +local times is not recommended. Unfortunately, you cannot just pass +a ``tzinfo`` argument when constructing a datetime (see the next +section for more details) + +>>> dt = datetime(2002, 10, 27, 1, 30, 0) +>>> dt1 = eastern.localize(dt, is_dst=True) +>>> dt1.strftime(fmt) +'2002-10-27 01:30:00 EDT-0400' +>>> dt2 = eastern.localize(dt, is_dst=False) +>>> dt2.strftime(fmt) +'2002-10-27 01:30:00 EST-0500' + +Converting between timezones also needs special attention. This also +needs to use the ``normalize()`` method to ensure the conversion is +correct. + +>>> utc_dt = utc.localize(datetime.utcfromtimestamp(1143408899)) +>>> utc_dt.strftime(fmt) +'2006-03-26 21:34:59 UTC+0000' +>>> au_tz = timezone('Australia/Sydney') +>>> au_dt = au_tz.normalize(utc_dt.astimezone(au_tz)) +>>> au_dt.strftime(fmt) +'2006-03-27 08:34:59 EST+1100' +>>> utc_dt2 = utc.normalize(au_dt.astimezone(utc)) +>>> utc_dt2.strftime(fmt) +'2006-03-26 21:34:59 UTC+0000' + +You can take shortcuts when dealing with the UTC side of timezone +conversions. ``normalize()`` and ``localize()`` are not really +necessary when there are no daylight savings time transitions to +deal with. + +>>> utc_dt = datetime.utcfromtimestamp(1143408899).replace(tzinfo=utc) +>>> utc_dt.strftime(fmt) +'2006-03-26 21:34:59 UTC+0000' +>>> au_tz = timezone('Australia/Sydney') +>>> au_dt = au_tz.normalize(utc_dt.astimezone(au_tz)) +>>> au_dt.strftime(fmt) +'2006-03-27 08:34:59 EST+1100' +>>> utc_dt2 = au_dt.astimezone(utc) +>>> utc_dt2.strftime(fmt) +'2006-03-26 21:34:59 UTC+0000' + + +``tzinfo`` API +-------------- + +The ``tzinfo`` instances returned by the ``timezone()`` function have +been extended to cope with ambiguous times by adding an ``is_dst`` +parameter to the ``utcoffset()``, ``dst()`` && ``tzname()`` methods. + +>>> tz = timezone('America/St_Johns') + +>>> normal = datetime(2009, 9, 1) +>>> ambiguous = datetime(2009, 10, 31, 23, 30) + +the ``is_dst`` parameter is ignormed for most timestamps, but +is used to resolve the ambiguity during ambiguous periods caused +to DST transitions. + +>>> tz.utcoffset(normal, is_dst=True) +datetime.timedelta(-1, 77400) +>>> tz.dst(normal, is_dst=True) +datetime.timedelta(0, 3600) +>>> tz.tzname(normal, is_dst=True) +'NDT' + +>>> tz.utcoffset(ambiguous, is_dst=True) +datetime.timedelta(-1, 77400) +>>> tz.dst(ambiguous, is_dst=True) +datetime.timedelta(0, 3600) +>>> tz.tzname(ambiguous, is_dst=True) +'NDT' + +>>> tz.utcoffset(normal, is_dst=False) +datetime.timedelta(-1, 77400) +>>> tz.dst(normal, is_dst=False) +datetime.timedelta(0, 3600) +>>> tz.tzname(normal, is_dst=False) +'NDT' + +>>> tz.utcoffset(ambiguous, is_dst=False) +datetime.timedelta(-1, 73800) +>>> tz.dst(ambiguous, is_dst=False) +datetime.timedelta(0) +>>> tz.tzname(ambiguous, is_dst=False) +'NST' + +If ``is_dst`` is not specified, ambiguous timestamps will raise +an ``AmbiguousTimeError`` exception. + +>>> tz.utcoffset(normal) +datetime.timedelta(-1, 77400) +>>> tz.dst(normal) +datetime.timedelta(0, 3600) +>>> tz.tzname(normal) +'NDT' + +>>> tz.utcoffset(ambiguous) +Traceback (most recent call last): +[...] +AmbiguousTimeError: 2009-10-31 23:30:00 +>>> tz.dst(ambiguous) +Traceback (most recent call last): +[...] +AmbiguousTimeError: 2009-10-31 23:30:00 +>>> tz.tzname(ambiguous) +Traceback (most recent call last): +[...] +AmbiguousTimeError: 2009-10-31 23:30:00 + + +Problems with Localtime +~~~~~~~~~~~~~~~~~~~~~~~ + +The major problem we have to deal with is that certain datetimes +may occur twice in a year. For example, in the US/Eastern timezone +on the last Sunday morning in October, the following sequence +happens: + + - 01:00 EDT occurs + - 1 hour later, instead of 2:00am the clock is turned back 1 hour + and 01:00 happens again (this time 01:00 EST) + +In fact, every instant between 01:00 and 02:00 occurs twice. This means +that if you try and create a time in the 'US/Eastern' timezone using +the standard datetime syntax, there is no way to specify if you meant +before of after the end-of-daylight-savings-time transition. + +>>> loc_dt = datetime(2002, 10, 27, 1, 30, 00, tzinfo=eastern) +>>> loc_dt.strftime(fmt) +'2002-10-27 01:30:00 EST-0500' + +As you can see, the system has chosen one for you and there is a 50% +chance of it being out by one hour. For some applications, this does +not matter. However, if you are trying to schedule meetings with people +in different timezones or analyze log files it is not acceptable. + +The best and simplest solution is to stick with using UTC. The pytz +package encourages using UTC for internal timezone representation by +including a special UTC implementation based on the standard Python +reference implementation in the Python documentation. This timezone +unpickles to be the same instance, and pickles to a relatively small +size. The UTC implementation can be obtained as pytz.utc, pytz.UTC, +or pytz.timezone('UTC'). + +>>> import pickle, pytz +>>> dt = datetime(2005, 3, 1, 14, 13, 21, tzinfo=utc) +>>> naive = dt.replace(tzinfo=None) +>>> p = pickle.dumps(dt, 1) +>>> naive_p = pickle.dumps(naive, 1) +>>> len(p), len(naive_p), len(p) - len(naive_p) +(60, 43, 17) +>>> new = pickle.loads(p) +>>> new == dt +True +>>> new is dt +False +>>> new.tzinfo is dt.tzinfo +True +>>> pytz.utc is pytz.UTC is pytz.timezone('UTC') +True + +Note that this instance is not the same instance (or implementation) as +other timezones with the same meaning (GMT, Greenwich, Universal, etc.). + +>>> utc is pytz.timezone('GMT') +False + +If you insist on working with local times, this library provides a +facility for constructing them unambiguously: + +>>> loc_dt = datetime(2002, 10, 27, 1, 30, 00) +>>> est_dt = eastern.localize(loc_dt, is_dst=True) +>>> edt_dt = eastern.localize(loc_dt, is_dst=False) +>>> print est_dt.strftime(fmt), '/', edt_dt.strftime(fmt) +2002-10-27 01:30:00 EDT-0400 / 2002-10-27 01:30:00 EST-0500 + +If you pass None as the is_dst flag to localize(), pytz will refuse to +guess and raise exceptions if you try to build ambiguous or non-existent +times. + +For example, 1:30am on 27th Oct 2002 happened twice in the US/Eastern +timezone when the clocks where put back at the end of Daylight Savings +Time: + +>>> eastern.localize(datetime(2002, 10, 27, 1, 30, 00), is_dst=None) +Traceback (most recent call last): +... +AmbiguousTimeError: 2002-10-27 01:30:00 + +Similarly, 2:30am on 7th April 2002 never happened at all in the +US/Eastern timezone, as the clocks where put forward at 2:00am skipping +the entire hour: + +>>> eastern.localize(datetime(2002, 4, 7, 2, 30, 00), is_dst=None) +Traceback (most recent call last): +... +NonExistentTimeError: 2002-04-07 02:30:00 + +Both of these exceptions share a common base class to make error handling +easier: + +>>> isinstance(pytz.AmbiguousTimeError(), pytz.InvalidTimeError) +True +>>> isinstance(pytz.NonExistentTimeError(), pytz.InvalidTimeError) +True + +Although ``localize()`` handles many cases, it is still not possible +to handle all. In cases where countries change their timezone definitions, +cases like the end-of-daylight-savings-time occur with no way of resolving +the ambiguity. For example, in 1915 Warsaw switched from Warsaw time to +Central European time. So at the stroke of midnight on August 5th 1915 +the clocks were wound back 24 minutes creating an ambiguous time period +that cannot be specified without referring to the timezone abbreviation +or the actual UTC offset. In this case midnight happened twice, neither +time during a daylight savings time period: + +>>> warsaw = pytz.timezone('Europe/Warsaw') +>>> loc_dt1 = warsaw.localize(datetime(1915, 8, 4, 23, 59, 59), is_dst=False) +>>> loc_dt1.strftime(fmt) +'1915-08-04 23:59:59 WMT+0124' +>>> loc_dt2 = warsaw.localize(datetime(1915, 8, 5, 00, 00, 00), is_dst=False) +>>> loc_dt2.strftime(fmt) +'1915-08-05 00:00:00 CET+0100' +>>> str(loc_dt2 - loc_dt1) +'0:24:01' + +The only way of creating a time during the missing 24 minutes is +converting from another timezone - because neither of the timezones +involved where in daylight savings mode the API simply provides no way +to express it: + +>>> utc_dt = datetime(1915, 8, 4, 22, 36, tzinfo=pytz.utc) +>>> utc_dt.astimezone(warsaw).strftime(fmt) +'1915-08-04 23:36:00 CET+0100' + +The standard Python way of handling all these ambiguities is not to +handle them, such as demonstrated in this example using the US/Eastern +timezone definition from the Python documentation (Note that this +implementation only works for dates between 1987 and 2006 - it is +included for tests only!): + +>>> from pytz.reference import Eastern # pytz.reference only for tests +>>> dt = datetime(2002, 10, 27, 0, 30, tzinfo=Eastern) +>>> str(dt) +'2002-10-27 00:30:00-04:00' +>>> str(dt + timedelta(hours=1)) +'2002-10-27 01:30:00-05:00' +>>> str(dt + timedelta(hours=2)) +'2002-10-27 02:30:00-05:00' +>>> str(dt + timedelta(hours=3)) +'2002-10-27 03:30:00-05:00' + +Notice the first two results? At first glance you might think they are +correct, but taking the UTC offset into account you find that they are +actually two hours appart instead of the 1 hour we asked for. + +>>> from pytz.reference import UTC # pytz.reference only for tests +>>> str(dt.astimezone(UTC)) +'2002-10-27 04:30:00+00:00' +>>> str((dt + timedelta(hours=1)).astimezone(UTC)) +'2002-10-27 06:30:00+00:00' + + +Country Information +~~~~~~~~~~~~~~~~~~~ + +A mechanism is provided to access the timezones commonly in use +for a particular country, looked up using the ISO 3166 country code. +It returns a list of strings that can be used to retrieve the relevant +tzinfo instance using ``pytz.timezone()``: + +>>> pytz.country_timezones['nz'] +['Pacific/Auckland', 'Pacific/Chatham'] + +The Olson database comes with a ISO 3166 country code to English country +name mapping that pytz exposes as a dictionary: + +>>> pytz.country_names['nz'] +'New Zealand' + + +What is UTC +~~~~~~~~~~~ + +'UTC' is Universal Time, also known as Greenwich Mean Time or GMT +in the United Kingdom. All other timezones are given as offsets from +UTC. No daylight savings time occurs in UTC, making it a useful timezone +to perform date arithmetic without worrying about the confusion and +ambiguities caused by daylight savings time transitions, your country +changing its timezone, or mobile computers that move roam through +multiple timezones. + + +Helpers +~~~~~~~ + +There are two lists of timezones provided. + +``all_timezones`` is the exhaustive list of the timezone names that can +be used. + +>>> from pytz import all_timezones +>>> len(all_timezones) >= 500 +True +>>> 'Etc/Greenwich' in all_timezones +True + +``common_timezones`` is a list of useful, current timezones. It doesn't +contain deprecated zones or historical zones, except for a few I've +deemed in common usage, such as US/Eastern (open a bug report if you +think other timezones are deserving of being included here). It is also +a sequence of strings. + +>>> from pytz import common_timezones +>>> len(common_timezones) < len(all_timezones) +True +>>> 'Etc/Greenwich' in common_timezones +False +>>> 'Australia/Melbourne' in common_timezones +True +>>> 'US/Eastern' in common_timezones +True +>>> 'Canada/Eastern' in common_timezones +True +>>> 'US/Pacific-New' in all_timezones +True +>>> 'US/Pacific-New' in common_timezones +False + +Both ``common_timezones`` and ``all_timezones`` are alphabetically +sorted: + +>>> common_timezones_dupe = common_timezones[:] +>>> common_timezones_dupe.sort() +>>> common_timezones == common_timezones_dupe +True +>>> all_timezones_dupe = all_timezones[:] +>>> all_timezones_dupe.sort() +>>> all_timezones == all_timezones_dupe +True + +``all_timezones`` and ``common_timezones`` are also available as sets. + +>>> from pytz import all_timezones_set, common_timezones_set +>>> 'US/Eastern' in all_timezones_set +True +>>> 'US/Eastern' in common_timezones_set +True +>>> 'Australia/Victoria' in common_timezones_set +False + +You can also retrieve lists of timezones used by particular countries +using the ``country_timezones()`` function. It requires an ISO-3166 +two letter country code. + +>>> from pytz import country_timezones +>>> country_timezones('ch') +['Europe/Zurich'] +>>> country_timezones('CH') +['Europe/Zurich'] + + +License +~~~~~~~ + +MIT license. + +This code is also available as part of Zope 3 under the Zope Public +License, Version 2.1 (ZPL). + +I'm happy to relicense this code if necessary for inclusion in other +open source projects. + + +Latest Versions +~~~~~~~~~~~~~~~ + +This package will be updated after releases of the Olson timezone +database. The latest version can be downloaded from the `Python Package +Index <http://pypi.python.org/pypi/pytz/>`_. The code that is used +to generate this distribution is hosted on launchpad.net and available +using the `Bazaar version control system <http://bazaar-vcs.org>`_ +using:: + + bzr branch lp:pytz + + +Bugs, Feature Requests & Patches +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Bugs can be reported using `Launchpad <https://bugs.launchpad.net/pytz>`_. + + +Issues & Limitations +~~~~~~~~~~~~~~~~~~~~ + +- Offsets from UTC are rounded to the nearest whole minute, so timezones + such as Europe/Amsterdam pre 1937 will be up to 30 seconds out. This + is a limitation of the Python datetime library. + +- If you think a timezone definition is incorrect, I probably can't fix + it. pytz is a direct translation of the Olson timezone database, and + changes to the timezone definitions need to be made to this source. + If you find errors they should be reported to the time zone mailing + list, linked from http://www.twinsun.com/tz/tz-link.htm + + +Further Reading +~~~~~~~~~~~~~~~ + +More info than you want to know about timezones: +http://www.twinsun.com/tz/tz-link.htm + + +Contact +~~~~~~~ + +Stuart Bishop <st...@st...> + Modified: trunk/matplotlib/lib/pytz/__init__.py =================================================================== --- trunk/matplotlib/lib/pytz/__init__.py 2010-06-06 20:34:09 UTC (rev 8388) +++ trunk/matplotlib/lib/pytz/__init__.py 2010-06-06 20:52:36 UTC (rev 8389) @@ -8,29 +8,33 @@ on how to use these modules. ''' -# The Olson database has historically been updated about 4 times a year -OLSON_VERSION = '2008c' +# The Olson database is updated several times a year. +OLSON_VERSION = '2010h' VERSION = OLSON_VERSION +# Version format for a patch release - only one so far. #VERSION = OLSON_VERSION + '.2' __version__ = OLSON_VERSION OLSEN_VERSION = OLSON_VERSION # Old releases had this misspelling __all__ = [ - 'timezone', 'utc', 'country_timezones', - 'AmbiguousTimeError', 'UnknownTimeZoneError', + 'timezone', 'utc', 'country_timezones', 'country_names', + 'AmbiguousTimeError', 'InvalidTimeError', + 'NonExistentTimeError', 'UnknownTimeZoneError', 'all_timezones', 'all_timezones_set', 'common_timezones', 'common_timezones_set', ] import sys, datetime, os.path, gettext +from UserDict import DictMixin try: from pkg_resources import resource_stream except ImportError: resource_stream = None -from tzinfo import AmbiguousTimeError, unpickler +from tzinfo import AmbiguousTimeError, InvalidTimeError, NonExistentTimeError +from tzinfo import unpickler from tzfile import build_tzinfo # Use 2.3 sets module implementation if set builtin is not available @@ -43,20 +47,32 @@ def open_resource(name): """Open a resource from the zoneinfo subdir for reading. - Uses the pkg_resources module if available. + Uses the pkg_resources module if available and no standard file + found at the calculated location. """ - if resource_stream is not None: + name_parts = name.lstrip('/').split('/') + for part in name_parts: + if part == os.path.pardir or os.path.sep in part: + raise ValueError('Bad path segment: %r' % part) + filename = os.path.join(os.path.dirname(__file__), + 'zoneinfo', *name_parts) + if not os.path.exists(filename) and resource_stream is not None: + # http://bugs.launchpad.net/bugs/383171 - we avoid using this + # unless absolutely necessary to help when a broken version of + # pkg_resources is installed. return resource_stream(__name__, 'zoneinfo/' + name) - else: - name_parts = name.lstrip('/').split('/') - for part in name_parts: - if part == os.path.pardir or os.path.sep in part: - raise ValueError('Bad path segment: %r' % part) - filename = os.path.join(os.path.dirname(__file__), - 'zoneinfo', *name_parts) - return open(filename, 'rb') - + return open(filename, 'rb') + +def resource_exists(name): + """Return true if the given resource exists""" + try: + open_resource(name) + return True + except IOError: + return False + + # Enable this when we get some translations? # We want an i18n API that is useful to programs using Python's gettext # module, as well as the Zope3 i18n package. Perhaps we should just provide @@ -92,7 +108,7 @@ def timezone(zone): r''' Return a datetime.tzinfo implementation for the given timezone - + >>> from datetime import datetime, timedelta >>> utc = timezone('UTC') >>> eastern = timezone('US/Eastern') @@ -139,7 +155,7 @@ _tzinfo_cache[zone] = build_tzinfo(zone, open_resource(zone)) else: raise UnknownTimeZoneError(zone) - + return _tzinfo_cache[zone] @@ -154,7 +170,7 @@ class UTC(datetime.tzinfo): """UTC - + Identical to the reference UTC implementation given in Python docs except that it unpickles using the single module global instance defined beneath this class declaration. @@ -164,6 +180,10 @@ """ zone = "UTC" + _utcoffset = ZERO + _dst = ZERO + _tzname = zone + def utcoffset(self, dt): return ZERO @@ -172,7 +192,7 @@ def dst(self, dt): return ZERO - + def __reduce__(self): return _UTC, () @@ -200,14 +220,14 @@ def _UTC(): """Factory function for utc unpickling. - + Makes sure that unpickling a utc instance always returns the same module global. - + These examples belong in the UTC class above, but it is obscured; or in the README.txt, but we are not depending on Python 2.4 so integrating the README.txt examples with the unit tests is not trivial. - + >>> import datetime, pickle >>> dt = datetime.datetime(2005, 3, 1, 14, 13, 21, tzinfo=utc) >>> naive = dt.replace(tzinfo=None) @@ -240,38 +260,85 @@ return unpickler(*args) _p.__safe_for_unpickling__ = True -_country_timezones_cache = {} -def country_timezones(iso3166_code): - """Return a list of timezones used in a particular country. +class _LazyDict(DictMixin): + """Dictionary populated on first use.""" + data = None + def __getitem__(self, key): + if self.data is None: + self._fill() + return self.data[key.upper()] + def keys(self): + if self.data is None: + self._fill() + return self.data.keys() + + +class _CountryTimezoneDict(_LazyDict): + """Map ISO 3166 country code to a list of timezone names commonly used + in that country. + iso3166_code is the two letter code used to identify the country. - >>> country_timezones('ch') + >>> country_timezones['ch'] ['Europe/Zurich'] - >>> country_timezones('CH') + >>> country_timezones['CH'] ['Europe/Zurich'] - >>> country_timezones(u'ch') + >>> country_timezones[u'ch'] ['Europe/Zurich'] - >>> country_timezones('XXX') + >>> country_timezones['XXX'] Traceback (most recent call last): ... KeyError: 'XXX' + + Previously, this information was exposed as a function rather than a + dictionary. This is still supported:: + + >>> country_timezones('nz') + ['Pacific/Auckland', 'Pacific/Chatham'] """ - iso3166_code = iso3166_code.upper() - if not _country_timezones_cache: + def __call__(self, iso3166_code): + """Backwards compatibility.""" + return self[iso3166_code] + + def _fill(self): + data = {} zone_tab = open_resource('zone.tab') for line in zone_tab: if line.startswith('#'): continue code, coordinates, zone = line.split(None, 4)[:3] + if zone not in all_timezones_set: + continue try: - _country_timezones_cache[code].append(zone) + data[code].append(zone) except KeyError: - _country_timezones_cache[code] = [zone] - return _country_timezones_cache[iso3166_code] + data[code] = [zone] + self.data = data +country_timezones = _CountryTimezoneDict() + +class _CountryNameDict(_LazyDict): + '''Dictionary proving ISO3166 code -> English name. + + >>> country_names['au'] + 'Australia' + ''' + def _fill(self): + data = {} + zone_tab = open_resource('iso3166.tab') + for line in zone_tab.readlines(): + if line.startswith('#'): + continue + code, name = line.split(None, 1) + data[code] = name.strip() + self.data = data + +country_names = _CountryNameDict() + + # Time-zone info based solely on fixed offsets class _FixedOffset(datetime.tzinfo): @@ -292,7 +359,7 @@ def dst(self, dt): return None - + def tzname(self, dt): return None @@ -314,7 +381,7 @@ def FixedOffset(offset, _tzinfos = {}): """return a fixed-offset timezone based off a number of minutes. - + >>> one = FixedOffset(-330) >>> one pytz.FixedOffset(-330) @@ -326,7 +393,7 @@ pytz.FixedOffset(1380) >>> two.utcoffset(datetime.datetime.now()) datetime.timedelta(0, 82800) - + The datetime.timedelta must be between the range of -1 and 1 day, non-inclusive. @@ -347,7 +414,7 @@ There should always be only one instance of a FixedOffset per timedelta. This should be true for multiple creation calls. - + >>> FixedOffset(-330) is one True >>> FixedOffset(1380) is two @@ -386,7 +453,7 @@ if __name__ == '__main__': _test() -common_timezones = \ +all_timezones = \ ['Africa/Abidjan', 'Africa/Accra', 'Africa/Addis_Ababa', @@ -445,6 +512,19 @@ 'America/Anguilla', 'America/Antigua', 'America/Araguaina', + 'America/Argentina/Buenos_Aires', + 'America/Argentina/Catamarca', + 'America/Argentina/ComodRivadavia', + 'America/Argentina/Cordoba', + 'America/Argentina/Jujuy', + 'America/Argentina/La_Rioja', + 'America/Argentina/Mendoza', + 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Salta', + 'America/Argentina/San_Juan', + 'America/Argentina/San_Luis', + 'America/Argentina/Tucuman', + 'America/Argentina/Ushuaia', 'America/Aruba', 'America/Asuncion', 'America/Atikokan', @@ -496,12 +576,22 @@ 'America/Halifax', 'America/Havana', 'America/Hermosillo', + 'America/Indiana/Indianapolis', + 'America/Indiana/Knox', + 'America/Indiana/Marengo', + 'America/Indiana/Petersburg', + 'America/Indiana/Tell_City', + 'America/Indiana/Vevay', + 'America/Indiana/Vincennes', + 'America/Indiana/Winamac', 'America/Indianapolis', 'America/Inuvik', 'America/Iqaluit', 'America/Jamaica', 'America/Jujuy', 'America/Juneau', + 'America/Kentucky/Louisville', + 'America/Kentucky/Monticello', 'America/Knox_IN', 'America/La_Paz', 'America/Lima', @@ -512,6 +602,7 @@ 'America/Manaus', 'America/Marigot', 'America/Martinique', + 'America/Matamoros', 'America/Mazatlan', 'America/Mendoza', 'America/Menominee', @@ -528,6 +619,9 @@ 'America/Nipigon', 'America/Nome', 'America/Noronha', + 'America/North_Dakota/Center', + 'America/North_Dakota/New_Salem', + 'America/Ojinaga', 'America/Panama', 'America/Pangnirtung', 'America/Paramaribo', @@ -544,6 +638,8 @@ 'America/Resolute', 'America/Rio_Branco', 'America/Rosario', + 'America/Santa_Isabel', + 'America/Santarem', 'America/Santiago', 'America/Santo_Domingo', 'America/Sao_Paulo', @@ -571,6 +667,7 @@ 'Antarctica/Casey', 'Antarctica/Davis', 'Antarctica/DumontDUrville', + 'Antarctica/Macquarie', 'Antarctica/Mawson', 'Antarctica/McMurdo', 'Antarctica/Palmer', @@ -619,6 +716,7 @@ 'Asia/Kamchatka', 'Asia/Karachi', 'Asia/Kashgar', + 'Asia/Kathmandu', 'Asia/Katmandu', 'Asia/Kolkata', 'Asia/Krasnoyarsk', @@ -632,6 +730,7 @@ 'Asia/Manila', 'Asia/Muscat', 'Asia/Nicosia', + 'Asia/Novokuznetsk', 'Asia/Novosibirsk', 'Asia/Omsk', 'Asia/Oral', @@ -704,6 +803,8 @@ 'Brazil/DeNoronha', 'Brazil/East', 'Brazil/West', + 'CET', + 'CST6CDT', 'Canada/Atlantic', 'Canada/Central', 'Canada/East-Saskatchewan', @@ -715,6 +816,47 @@ 'Canada/Yukon', 'Chile/Continental', 'Chile/EasterIsland', + 'Cuba', + 'EET', + 'EST', + 'EST5EDT', + 'Egypt', + 'Eire', + 'Etc/GMT', + 'Etc/GMT+0', + 'Etc/GMT+1', + 'Etc/GMT+10', + 'Etc/GMT+11', + 'Etc/GMT+12', + 'Etc/GMT+2', + 'Etc/GMT+3', + 'Etc/GMT+4', + 'Etc/GMT+5', + 'Etc/GMT+6', + 'Etc/GMT+7', + 'Etc/GMT+8', + 'Etc/GMT+9', + 'Etc/GMT-0', + 'Etc/GMT-1', + 'Etc/GMT-10', + 'Etc/GMT-11', + 'Etc/GMT-12', + 'Etc/GMT-13', + 'Etc/GMT-14', + 'Etc/GMT-2', + 'Etc/GMT-3', + 'Etc/GMT-4', + 'Etc/GMT-5', + 'Etc/GMT-6', + 'Etc/GMT-7', + 'Etc/GMT-8', + 'Etc/GMT-9', + 'Etc/GMT0', + 'Etc/Greenwich', + 'Etc/UCT', + 'Etc/UTC', + 'Etc/Universal', + 'Etc/Zulu', 'Europe/Amsterdam', 'Europe/Andorra', 'Europe/Athens', @@ -773,7 +915,16 @@ 'Europe/Zagreb', 'Europe/Zaporozhye', 'Europe/Zurich', + 'GB', + 'GB-Eire', 'GMT', + 'GMT+0', + 'GMT-0', + 'GMT0', + 'Greenwich', + 'HST', + 'Hongkong', + 'Iceland', 'Indian/Antananarivo', 'Indian/Chagos', 'Indian/Christmas', @@ -785,9 +936,23 @@ 'Indian/Mauritius', 'Indian/Mayotte', 'Indian/Reunion', + 'Iran', + 'Israel', + 'Jamaica', + 'Japan', + 'Kwajalein', + 'Libya', + 'MET', + 'MST', + 'MST7MDT', 'Mexico/BajaNorte', 'Mexico/BajaSur', 'Mexico/General', + 'NZ', + 'NZ-CHAT', + 'Navajo', + 'PRC', + 'PST8PDT', 'Pacific/Apia', 'Pacific/Auckland', 'Pacific/Chatham', @@ -828,6 +993,13 @@ 'Pacific/Wake', 'Pacific/Wallis', 'Pacific/Yap', + 'Poland', + 'Portugal', + 'ROC', + 'ROK', + 'Singapore', + 'Turkey', + 'UCT', 'US/Alaska', 'US/Aleutian', 'US/Arizona', @@ -841,16 +1013,21 @@ 'US/Pacific', 'US/Pacific-New', 'US/Samoa', - 'UTC'] -common_timezones_set = set(common_timezones) - -all_timezones = \ + 'UTC', + 'Universal', + 'W-SU', + 'WET', + 'Zulu'] +all_timezones = [ + tz for tz in all_timezones if resource_exists(tz)] + +all_timezones_set = set(all_timezones) +common_timezones = \ ['Africa/Abidjan', 'Africa/Accra', 'Africa/Addis_Ababa', 'Africa/Algiers', 'Africa/Asmara', - 'Africa/Asmera', 'Africa/Bamako', 'Africa/Bangui', 'Africa/Banjul', @@ -894,7 +1071,6 @@ 'Africa/Ouagadougou', 'Africa/Porto-Novo', 'Africa/Sao_Tome', - 'Africa/Timbuktu', 'Africa/Tripoli', 'Africa/Tunis', 'Africa/Windhoek', @@ -905,12 +1081,12 @@ 'America/Araguaina', 'America/Argentina/Buenos_Aires', 'America/Argentina/Catamarca', - 'America/Argentina/ComodRivadavia', 'America/Argentina/Cordoba', 'America/Argentina/Jujuy', 'America/Argentina/La_Rioja', 'America/Argentina/Mendoza', 'America/Argentina/Rio_Gallegos', + 'America/Argentina/Salta', 'America/Argentina/San_Juan', 'America/Argentina/San_Luis', 'America/Argentina/Tucuman', @@ -918,7 +1094,6 @@ 'America/Aruba', 'America/Asuncion', 'America/Atikokan', - 'America/Atka', 'America/Bahia', 'America/Barbados', 'America/Belem', @@ -927,18 +1102,14 @@ 'America/Boa_Vista', 'America/Bogota', 'America/Boise', - 'America/Buenos_Aires', 'America/Cambridge_Bay', 'America/Campo_Grande', 'America/Cancun', 'America/Caracas', - 'America/Catamarca', 'America/Cayenne', 'America/Cayman', 'America/Chicago', 'America/Chihuahua', - 'America/Coral_Harbour', - 'America/Cordoba', 'America/Costa_Rica', 'America/Cuiaba', 'America/Curacao', @@ -951,8 +1122,6 @@ 'America/Edmonton', 'America/Eirunepe', 'America/El_Salvador', - 'America/Ensenada', - 'America/Fort_Wayne', 'America/Fortaleza', 'America/Glace_Bay', 'America/Godthab', @@ -974,26 +1143,21 @@ 'America/Indiana/Vevay', 'America/Indiana/Vincennes', 'America/Indiana/Winamac', - 'America/Indianapolis', 'America/Inuvik', 'America/Iqaluit', 'America/Jamaica', - 'America/Jujuy', 'America/Juneau', 'America/Kentucky/Louisville', 'America/Kentucky/Monticello', - 'America/Knox_IN', 'America/La_Paz', 'America/Lima', 'America/Los_Angeles', - 'America/Louisville', 'America/Maceio', 'America/Managua', 'America/Manaus', - 'America/Marigot', 'America/Martinique', + 'America/Matamoros', 'America/Mazatlan', - 'America/Mendoza', 'America/Menominee', 'America/Merida', 'America/Mexico_City', @@ -1010,13 +1174,13 @@ 'America/Noronha', 'America/North_Dakota/Center', 'America/North_Dakota/New_Salem', + 'America/Ojinaga', 'America/Panama', 'America/Pangnirtung', 'America/Paramaribo', 'America/Phoenix', 'America/Port-au-Prince', 'America/Port_of_Spain', - 'America/Porto_Acre', 'America/Porto_Velho', 'America/Puerto_Rico', 'America/Rainy_River', @@ -1025,13 +1189,12 @@ 'America/Regina', 'America/Resolute', 'America/Rio_Branco', - 'America/Rosario', + 'America/Santa_Isabel', + 'America/Santarem', 'America/Santiago', 'America/Santo_Domingo', 'America/Sao_Paulo', 'America/Scoresbysund', - 'America/Shiprock', - 'America/St_Barthelemy', 'America/St_Johns', 'America/St_Kitts', 'America/St_Lucia', @@ -1045,7 +1208,6 @@ 'America/Toronto', 'America/Tortola', 'America/Vancouver', - 'America/Virgin', 'America/Whitehorse', 'America/Winnipeg', 'America/Yakutat', @@ -1053,14 +1215,13 @@ 'Antarctica/Casey', 'Antarctica/Davis', 'Antarctica/DumontDUrville', + 'Antarctica/Macquarie', 'Antarctica/Mawson', 'Antarctica/McMurdo', 'Antarctica/Palmer', 'Antarctica/Rothera', - 'Antarctica/South_Pole', 'Antarctica/Syowa', 'Antarctica/Vostok', - 'Arctic/Longyearbyen', 'Asia/Aden', 'Asia/Almaty', 'Asia/Amman', @@ -1068,7 +1229,6 @@ 'Asia/Aqtau', 'Asia/Aqtobe', 'Asia/Ashgabat', - 'Asia/Ashkhabad', 'Asia/Baghdad', 'Asia/Bahrain', 'Asia/Baku', @@ -1076,12 +1236,9 @@ 'Asia/Beirut', 'Asia/Bishkek', 'Asia/Brunei', - 'Asia/Calcutta', 'Asia/Choibalsan', 'Asia/Chongqing', - 'Asia/Chungking', 'Asia/Colombo', - 'Asia/Dacca', 'Asia/Damascus', 'Asia/Dhaka', 'Asia/Dili', @@ -1093,7 +1250,6 @@ 'Asia/Hong_Kong', 'Asia/Hovd', 'Asia/Irkutsk', - 'Asia/Istanbul', 'Asia/Jakarta', 'Asia/Jayapura', 'Asia/Jerusalem', @@ -1101,19 +1257,19 @@ 'Asia/Kamchatka', 'Asia/Karachi', 'Asia/Kashgar', - 'Asia/Katmandu', + 'Asia/Kathmandu', 'Asia/Kolkata', 'Asia/Krasnoyarsk', 'Asia/Kuala_Lumpur', 'Asia/Kuching', 'Asia/Kuwait', - 'Asia/Macao', 'Asia/Macau', 'Asia/Magadan', 'Asia/Makassar', 'Asia/Manila', 'Asia/Muscat', 'Asia/Nicosia', + 'Asia/Novokuznetsk', 'Asia/Novosibirsk', 'Asia/Omsk', 'Asia/Oral', @@ -1124,7 +1280,6 @@ 'Asia/Qyzylorda', 'Asia/Rangoon', 'Asia/Riyadh', - 'Asia/Saigon', 'Asia/Sakhalin', 'Asia/Samarkand', 'Asia/Seoul', @@ -1134,13 +1289,9 @@ 'Asia/Tashkent', 'Asia/Tbilisi', 'Asia/Tehran', - 'Asia/Tel_Aviv', - 'Asia/Thimbu', 'Asia/Thimphu', 'Asia/Tokyo', - 'Asia/Ujung_Pandang', 'Asia/Ulaanbaatar', - 'Asia/Ulan_Bator', 'Asia/Urumqi', 'Asia/Vientiane', 'Asia/Vladivostok', @@ -1151,102 +1302,35 @@ 'Atlantic/Bermuda', 'Atlantic/Canary', 'Atlantic/Cape_Verde', - 'Atlantic/Faeroe', 'Atlantic/Faroe', - 'Atlantic/Jan_Mayen', 'Atlantic/Madeira', 'Atlantic/Reykjavik', 'Atlantic/South_Georgia', 'Atlantic/St_Helena', 'Atlantic/Stanley', - 'Australia/ACT', 'Australia/Adelaide', 'Australia/Brisbane', 'Australia/Broken_Hill', - 'Australia/Canberra', 'Australia/Currie', 'Australia/Darwin', 'Australia/Eucla', 'Australia/Hobart', - 'Australia/LHI', 'Australia/Lindeman', 'Australia/Lord_Howe', 'Australia/Melbourne', - 'Australia/NSW', - 'Australia/North', 'Australia/Perth', - 'Australia/Queensland', - 'Australia/South', 'Australia/Sydney', - 'Australia/Tasmania', - 'Australia/Victoria', - 'Australia/West', - 'Australia/Yancowinna', - 'Brazil/Acre', - 'Brazil/DeNoronha', - 'Brazil/East', - 'Brazil/West', - 'CET', - 'CST6CDT', 'Canada/Atlantic', 'Canada/Central', - 'Canada/East-Saskatchewan', 'Canada/Eastern', 'Canada/Mountain', 'Canada/Newfoundland', 'Canada/Pacific', - 'Canada/Saskatchewan', - 'Canada/Yukon', - 'Chile/Continental', - 'Chile/EasterIsland', - 'Cuba', - 'EET', - 'EST', - 'EST5EDT', - 'Egypt', - 'Eire', - 'Etc/GMT', - 'Etc/GMT+0', - 'Etc/GMT+1', - 'Etc/GMT+10', - 'Etc/GMT+11', - 'Etc/GMT+12', - 'Etc/GMT+2', - 'Etc/GMT+3', - 'Etc/GMT+4', - 'Etc/GMT+5', - 'Etc/GMT+6', - 'Etc/GMT+7', - 'Etc/GMT+8', - 'Etc/GMT+9', - 'Etc/GMT-0', - 'Etc/GMT-1', - 'Etc/GMT-10', - 'Etc/GMT-11', - 'Etc/GMT-12', - 'Etc/GMT-13', - 'Etc/GMT-14', - 'Etc/GMT-2', - 'Etc/GMT-3', - 'Etc/GMT-4', - 'Etc/GMT-5', - 'Etc/GMT-6', - 'Etc/GMT-7', - 'Etc/GMT-8', - 'Etc/GMT-9', - 'Etc/GMT0', - 'Etc/Greenwich', - 'Etc/UCT', - 'Etc/UTC', - 'Etc/Universal', - 'Etc/Zulu', 'Europe/Amsterdam', 'Europe/Andorra', 'Europe/Athens', - 'Europe/Belfast', 'Europe/Belgrade', 'Europe/Berlin', - 'Europe/Bratislava', 'Europe/Brussels', 'Europe/Bucharest', 'Europe/Budapest', @@ -1254,60 +1338,38 @@ 'Europe/Copenhagen', 'Europe/Dublin', 'Europe/Gibraltar', - 'Europe/Guernsey', 'Europe/Helsinki', - 'Europe/Isle_of_Man', 'Europe/Istanbul', - 'Europe/Jersey', 'Europe/Kaliningrad', 'Europe/Kiev', 'Europe/Lisbon', - 'Europe/Ljubljana', 'Europe/London', 'Europe/Luxembourg', 'Europe/Madrid', 'Europe/Malta', - 'Europe/Mariehamn', 'Europe/Minsk', 'Europe/Monaco', 'Europe/Moscow', - 'Europe/Nicosia', 'Europe/Oslo', 'Europe/Paris', - 'Europe/Podgorica', 'Europe/Prague', 'Europe/Riga', 'Europe/Rome', 'Europe/Samara', - 'Europe/San_Marino', - 'Europe/Sarajevo', 'Europe/Simferopol', - 'Europe/Skopje', 'Europe/Sofia', 'Europe/Stockholm', 'Europe/Tallinn', 'Europe/Tirane', - 'Europe/Tiraspol', 'Europe/Uzhgorod', 'Europe/Vaduz', - 'Europe/Vatican', 'Europe/Vienna', 'Europe/Vilnius', 'Europe/Volgograd', 'Europe/Warsaw', - 'Europe/Zagreb', 'Europe/Zaporozhye', 'Europe/Zurich', - 'GB', - 'GB-Eire', 'GMT', - 'GMT+0', - 'GMT-0', - 'GMT0', - 'Greenwich', - 'HST', - 'Hongkong', - 'Iceland', 'Indian/Antananarivo', 'Indian/Chagos', 'Indian/Christmas', @@ -1319,23 +1381,6 @@ 'Indian/Mauritius', 'Indian/Mayotte', 'Indian/Reunion', - 'Iran', - 'Israel', - 'Jamaica', - 'Japan', - 'Kwajalein', - 'Libya', - 'MET', - 'MST', - 'MST7MDT', - 'Mexico/BajaNorte', - 'Mexico/BajaSur', - 'Mexico/General', - 'NZ', - 'NZ-CHAT', - 'Navajo', - 'PRC', - 'PST8PDT', 'Pacific/Apia', 'Pacific/Auckland', 'Pacific/Chatham', @@ -1368,38 +1413,21 @@ 'Pacific/Port_Moresby', 'Pacific/Rarotonga', 'Pacific/Saipan', - 'Pacific/Samoa', 'Pacific/Tahiti', 'Pacific/Tarawa', 'Pacific/Tongatapu', 'Pacific/Truk', 'Pacific/Wake', 'Pacific/Wallis', - 'Pacific/Yap', - 'Poland', - 'Portugal', - 'ROC', - 'ROK', - 'Singapore', - 'Turkey', - 'UCT', 'US/Alaska', - 'US/Aleutian', 'US/Arizona', 'US/Central', - 'US/East-Indiana', 'US/Eastern', 'US/Hawaii', - 'US/Indiana-Starke', - 'US/Michigan', 'US/Mountain', 'US/Pacific', - 'US/Pacific-New', - 'US/Samoa', - 'UTC', - 'Universal', - 'W-SU', - 'WET', - 'Zulu', - 'posixrules'] -all_timezones_set = set(all_timezones) + 'UTC'] +common_timezones = [ + tz for tz in common_timezones if tz in all_timezones] + +common_timezones_set = set(common_timezones) Added: trunk/matplotlib/lib/pytz/tests/test_docs.py =================================================================== --- trunk/matplotlib/lib/pytz/tests/test_docs.py (rev 0) +++ trunk/matplotlib/lib/pytz/tests/test_docs.py 2010-06-06 20:52:36 UTC (rev 8389) @@ -0,0 +1,35 @@ +# -*- coding: ascii -*- + +import unittest, os, os.path, sys +from doctest import DocTestSuite + +# We test the documentation this way instead of using DocFileSuite so +# we can run the tests under Python 2.3 +def test_README(): + pass + +this_dir = os.path.dirname(__file__) +locs = [ + os.path.join(this_dir, os.pardir, 'README.txt'), + os.path.join(this_dir, os.pardir, os.pardir, 'README.txt'), + ] +for loc in locs: + if os.path.exists(loc): + test_README.__doc__ = open(loc).read() + break +if test_README.__doc__ is None: + raise RuntimeError('README.txt not found') + + +def test_suite(): + "For the Z3 test runner" + return DocTestSuite() + + +if __name__ == '__main__': + sys.path.insert(0, os.path.abspath(os.path.join( + this_dir, os.pardir, os.pardir + ))) + unittest.main(defaultTest='test_suite') + + Added: trunk/matplotlib/lib/pytz/tests/test_tzinfo.py =================================================================== --- trunk/matplotlib/lib/pytz/tests/test_tzinfo.py (rev 0) +++ trunk/matplotlib/lib/pytz/tests/test_tzinfo.py 2010-06-06 20:52:36 UTC (rev 8389) @@ -0,0 +1,656 @@ +# -*- coding: ascii -*- + +import sys, os, os.path +import unittest, doctest +import cPickle as pickle +from datetime import datetime, time, timedelta, tzinfo + +if __name__ == '__main__': + # Only munge path if invoked as a script. Testrunners should have setup + # the paths already + sys.path.insert(0, os.path.abspath(os.path.join(os.pardir, os.pardir))) + +import pytz +from pytz import reference +from pytz.tzinfo import StaticTzInfo + +# I test for expected version to ensure the correct version of pytz is +# actually being tested. +EXPECTED_VERSION='2010h' + +fmt = '%Y-%m-%d %H:%M:%S %Z%z' + +NOTIME = timedelta(0) + +# GMT is a tzinfo.StaticTzInfo--the class we primarily want to test--while +# UTC is reference implementation. They both have the same timezone meaning. +UTC = pytz.timezone('UTC') +GMT = pytz.timezone('GMT') +assert isinstance(GMT, StaticTzInfo), 'GMT is no longer a StaticTzInfo' + + +def prettydt(dt): + """datetime as a string using a known format. + + We don't use strftime as it doesn't handle years earlier than 1900 + per http://bugs.python.org/issue1777412 + """ + if dt.utcoffset() >= timedelta(0): + offset = '+%s' % (dt.utcoffset(),) + else: + offset = '-%s' % (-1 * dt.utcoffset(),) + return '%04d-%02d-%02d %02d:%02d:%02d %s %s' % ( + dt.year, dt.month, dt.day, + dt.hour, dt.minute, dt.second, + dt.tzname(), offset) + +class BasicTest(unittest.TestCase): + + def testVersion(self): + # Ensuring the correct version of pytz has been loaded + self.failUnlessEqual(EXPECTED_VERSION, pytz.__version__, + 'Incorrect pytz version loaded. Import path is stuffed ' + 'or this test needs updating. (Wanted %s, got %s)' + % (EXPECTED_VERSION, pytz.__version__) + ) + + def testGMT(self): + now = datetime.now(tz=GMT) + self.failUnless(now.utcoffset() == NOTIME) + self.failUnless(now.dst() == NOTIME) + self.failUnless(now.timetuple() == now.utctimetuple()) + self.failUnless(now==now.replace(tzinfo=UTC)) + + def testReferenceUTC(self): + now = datetime.now(tz=UTC) + self.failUnless(now.utcoffset() == NOTIME) + self.failUnless(now.dst() == NOTIME) + self.failUnless(now.timetuple() == now.utctimetuple()) + + def testUnknownOffsets(self): + # This tzinfo behavior is required to make + # datetime.time.{utcoffset, dst, tzname} work as documented. + + dst_tz = pytz.timezone('US/Eastern') + + # This information is not known when we don't have a date, + # so return None per API. + self.failUnless(dst_tz.utcoffset(None) is None) + self.failUnless(dst_tz.dst(None) is None) + # We don't know the abbreviation, but this is still a valid + # tzname per the Python documentation. + self.failUnlessEqual(dst_tz.tzname(None), 'US/Eastern') + + +class PicklingTest(unittest.TestCase): + + def _roundtrip_tzinfo(self, tz): + p = pickle.dumps(tz) + unpickled_tz = pickle.loads(p) + self.failUnless(tz is unpickled_tz, '%s did not roundtrip' % tz.zone) + + def _roundtrip_datetime(self, dt): + # Ensure that the tzinfo attached to a datetime instance + # is identical to the one returned. This is important for + # DST timezones, as some state is stored in the tzinfo. + tz = dt.tzinfo + p = pickle.dumps(dt) + unpickled_dt = pickle.loads(p) + unpickled_tz = unpickled_dt.tzinfo + self.failUnless(tz is unpickled_tz, '%s did not roundtrip' % tz.zone) + + def testDst(self): + tz = pytz.timezone('Europe/Amsterdam') + dt = datetime(2004, 2, 1, 0, 0, 0) + + for localized_tz in tz._tzinfos.values(): + self._roundtrip_tzinfo(localized_tz) + self._roundtrip_datetime(dt.replace(tzinfo=localized_tz)) + + def testRoundtrip(self): + dt = datetime(2004, 2, 1, 0, 0, 0) + for zone in pytz.all_timezones: + tz = pytz.timezone(zone) + self._roundtrip_tzinfo(tz) + + def testDatabaseFixes(self): + # Hack the pickle to make it refer to a timezone abbreviation + # that does not match anything. The unpickler should be able + # to repair this case + tz = pytz.timezone('Australia/Melbourne') + p = pickle.dumps(tz) + tzname = tz._tzname + hacked_p = p.replace(tzname, '???') + self.failIfEqual(p, hacked_p) + unpickled_tz = pickle.loads(hacked_p) + self.failUnless(tz is unpickled_tz) + + # Simulate a database correction. In this case, the incorrect + # data will continue to be used. + p = pickle.dumps(tz) + new_utcoffset = tz._utcoffset.seconds + 42 + hacked_p = p.replace(str(tz._utcoffset.seconds), str(new_utcoffset)) + self.failIfEqual(p, hacked_p) + unpickled_tz = pickle.loads(hacked_p) + self.failUnlessEqual(unpickled_tz._utcoffset.seconds, new_utcoffset) + self.failUnless(tz is not unpickled_tz) + + def testOldPickles(self): + # Ensure that applications serializing pytz instances as pickles + # have no troubles upgrading to a new pytz release. These pickles + # where created with pytz2006j + east1 = pickle.loads( + "cpytz\n_p\np1\n(S'US/Eastern'\np2\nI-18000\n" + "I0\nS'EST'\np3\ntRp4\n." + ) + east2 = pytz.timezone('US/Eastern') + self.failUnless(east1 is east2) + + # Confirm changes in name munging between 2006j and 2007c cause + # no problems. + pap1 = pickle.loads( + "cpytz\n_p\np1\n(S'America/Port_minus_au_minus_Prince'" + "\np2\nI-17340\nI0\nS'PPMT'\np3\ntRp4\n." + ) + pap2 = pytz.timezone('America/Port-au-Prince') + self.failUnless(pap1 is pap2) + + gmt1 = pickle.loads("cpytz\n_p\np1\n(S'Etc/GMT_plus_10'\np2\ntRp3\n.") + gmt2 = pytz.timezone('Etc/GMT+10') + self.failUnless(gmt1 is gmt2) + + +class USEasternDSTStartTestCase(unittest.TestCase): + tzinfo = pytz.timezone('US/Eastern') + + # 24 hours before DST changeover + transition_time = datetime(2002, 4, 7, 7, 0, 0, tzinfo=UTC) + + # Increase for 'flexible' DST transitions due to 1 minute granularity + # of Python's datetime library + instant = timedelta(seconds=1) + + # before transition + before = { + 'tzname': 'EST', + 'utcoffset': timedelta(hours = -5), + 'dst': timedelta(hours = 0), + } + + # after transition + after = { + 'tzname': 'EDT', + 'utcoffset': timedelta(hours = -4), + 'dst': timedelta(hours = 1), + } + + def _test_tzname(self, utc_dt, wanted): + tzname = wanted['tzname'] + dt = utc_dt.astimezone(self.tzinfo) + self.failUnlessEqual(dt.tzname(), tzname, + 'Expected %s as tzname for %s. Got %s' % ( + tzname, str(utc_dt), dt.tzname() + ) + ) + + def _test_utcoffset(self, utc_dt, wanted): + utcoffset = wanted['utcoffset'] + dt = utc_dt.astimezone(self.tzinfo) + self.failUnlessEqual( + dt.utcoffset(), wanted['utcoffset'], + 'Expected %s as utcoffset for %s. Got %s' % ( + utcoffset, utc_dt, dt.utcoffset() + ) + ) + + def _test_dst(self, utc_dt, wanted): + dst = wanted['dst'] + dt = utc_dt.astimezone(self.tzinfo) + self.failUnlessEqual(dt.dst(),dst, + 'Expected %s as dst for %s. Got %s' % ( + dst, utc_dt, dt.dst() + ) + ) + + def test_arithmetic(self): + utc_dt = self.transition_time + + for days in range(-420, 720, 20): + delta = timedelta(days=days) + + # Make sure we can get back where we started + dt = utc_dt.astimezone(self.tzinfo) + dt2 = dt + delta + dt2 = dt2 - delta + self.failUnlessEqual(dt, dt2) + + # Make sure arithmetic crossing DST boundaries ends + # up in the correct timezone after normalization + utc_plus_delta = (utc_dt + delta).astimezone(self.tzinfo) + local_plus_delta = self.tzinfo.normalize(dt + delta) + self.failUnlessEqual( + prettydt(utc_plus_delta), + prettydt(local_plus_delta), + 'Incorrect result for delta==%d days. Wanted %r. Got %r'%( + days, + prettydt(utc_plus_delta), + prettydt(local_plus_delta), + ) + ) + + def _test_all(self, utc_dt, wanted): + self._test_utcoffset(utc_dt, wanted) + self._test_tzname(utc_dt, wanted) + self._test_dst(utc_dt, wanted) + + def testDayBefore(self): + self._test_all( + self.transition_time - timedelta(days=1), self.before + ) + + def testTwoHoursBefore(self): + self._test_all( + self.transition_time - timedelta(hours=2), self.before + ) + + def testHourBefore(self): + self._test_all( + self.transition_time - timedelta(hours=1), self.before + ) + + def testInstantBefore(self): + self._test_all( + self.transition_time - self.instant, self.before + ) + + def testTransition(self): + self._test_all( + self.transition_time, self.after + ) + + def testInstantAfter(self): + self._test_all( + self.transition_time + self.instant, self.after + ) + + def testHourAfter(self): + self._test_all( + self.transition_time + timedelta(hours=1), self.after + ) + + def testTwoHoursAfter(self): + self._test_all( + self.transition_time + timedelta(hours=1), self.after + ) + + def testDayAfter(self): + self._test_all( + self.transition_time + timedelta(days=1), self.after + ) + + +class USEasternDSTEndTestCase(USEasternDSTStartTestCase): + tzinfo = pytz.timezone('US/Eastern') + transition_time = datetime(2002, 10, 27, 6, 0, 0, tzinfo=UTC) + before = { + ... [truncated message content] |