aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorniemeyer <>2005-02-23 18:33:30 +0000
committerniemeyer <>2005-02-23 18:33:30 +0000
commitdebf3cd82a0aa85949c84eefa13eab5fd5be3949 (patch)
treedc73cefb189c3bb02209ded216fdd74405142f72
parentf57df0b03af23f5459cb6bc04fdc4a02e58eac50 (diff)
downloaddateutil-debf3cd82a0aa85949c84eefa13eab5fd5be3949.tar.gz
- Now tzfile() will unpickle to the updated file.
- Adding tzwin.py, contributed by Jeffrey Harris. - Minor tweaks in setup.py. - Adding README and example.py. - Putting old scheduler.py in the sandbox.
-rw-r--r--LICENSE259
-rw-r--r--MANIFEST.in2
-rw-r--r--dateutil/tz.py28
-rw-r--r--dateutil/tzwin.py155
-rw-r--r--dateutil/zoneinfo/__init__.py4
-rw-r--r--example.py15
-rw-r--r--sandbox/scheduler.py157
-rw-r--r--setup.py10
8 files changed, 620 insertions, 10 deletions
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..c5b5923
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,259 @@
+A. HISTORY OF THE SOFTWARE
+==========================
+
+Python was created in the early 1990s by Guido van Rossum at Stichting
+Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands
+as a successor of a language called ABC. Guido remains Python's
+principal author, although it includes many contributions from others.
+
+In 1995, Guido continued his work on Python at the Corporation for
+National Research Initiatives (CNRI, see http://www.cnri.reston.va.us)
+in Reston, Virginia where he released several versions of the
+software.
+
+In May 2000, Guido and the Python core development team moved to
+BeOpen.com to form the BeOpen PythonLabs team. In October of the same
+year, the PythonLabs team moved to Digital Creations (now Zope
+Corporation, see http://www.zope.com). In 2001, the Python Software
+Foundation (PSF, see http://www.python.org/psf/) was formed, a
+non-profit organization created specifically to own Python-related
+Intellectual Property. Zope Corporation is a sponsoring member of
+the PSF.
+
+All Python releases are Open Source (see http://www.opensource.org for
+the Open Source Definition). Historically, most, but not all, Python
+releases have also been GPL-compatible; the table below summarizes
+the various releases.
+
+ Release Derived Year Owner GPL-
+ from compatible? (1)
+
+ 0.9.0 thru 1.2 1991-1995 CWI yes
+ 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes
+ 1.6 1.5.2 2000 CNRI no
+ 2.0 1.6 2000 BeOpen.com no
+ 1.6.1 1.6 2001 CNRI yes (2)
+ 2.1 2.0+1.6.1 2001 PSF no
+ 2.0.1 2.0+1.6.1 2001 PSF yes
+ 2.1.1 2.1+2.0.1 2001 PSF yes
+ 2.2 2.1.1 2001 PSF yes
+ 2.1.2 2.1.1 2002 PSF yes
+ 2.1.3 2.1.2 2002 PSF yes
+ 2.2.1 2.2 2002 PSF yes
+ 2.2.2 2.2.1 2002 PSF yes
+ 2.2.3 2.2.2 2003 PSF yes
+ 2.3 2.2.2 2002-2003 PSF yes
+
+Footnotes:
+
+(1) GPL-compatible doesn't mean that we're distributing Python under
+ the GPL. All Python licenses, unlike the GPL, let you distribute
+ a modified version without making your changes open source. The
+ GPL-compatible licenses make it possible to combine Python with
+ other software that is released under the GPL; the others don't.
+
+(2) According to Richard Stallman, 1.6.1 is not GPL-compatible,
+ because its license has a choice of law clause. According to
+ CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1
+ is "not incompatible" with the GPL.
+
+Thanks to the many outside volunteers who have worked under Guido's
+direction to make these releases possible.
+
+
+B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON
+===============================================================
+
+PSF LICENSE AGREEMENT FOR PYTHON 2.3
+------------------------------------
+
+1. This LICENSE AGREEMENT is between the Python Software Foundation
+("PSF"), and the Individual or Organization ("Licensee") accessing and
+otherwise using Python 2.3 software in source or binary form and its
+associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement, PSF
+hereby grants Licensee a nonexclusive, royalty-free, world-wide
+license to reproduce, analyze, test, perform and/or display publicly,
+prepare derivative works, distribute, and otherwise use Python 2.3
+alone or in any derivative version, provided, however, that PSF's
+License Agreement and PSF's notice of copyright, i.e., "Copyright (c)
+2001, 2002, 2003 Python Software Foundation; All Rights Reserved" are
+retained in Python 2.3 alone or in any derivative version prepared by
+Licensee.
+
+3. In the event Licensee prepares a derivative work that is based on
+or incorporates Python 2.3 or any part thereof, and wants to make
+the derivative work available to others as provided herein, then
+Licensee hereby agrees to include in any such work a brief summary of
+the changes made to Python 2.3.
+
+4. PSF is making Python 2.3 available to Licensee on an "AS IS"
+basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.3 WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
+2.3 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
+A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.3,
+OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+6. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+7. Nothing in this License Agreement shall be deemed to create any
+relationship of agency, partnership, or joint venture between PSF and
+Licensee. This License Agreement does not grant permission to use PSF
+trademarks or trade name in a trademark sense to endorse or promote
+products or services of Licensee, or any third party.
+
+8. By copying, installing or otherwise using Python 2.3, Licensee
+agrees to be bound by the terms and conditions of this License
+Agreement.
+
+
+BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0
+-------------------------------------------
+
+BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1
+
+1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an
+office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
+Individual or Organization ("Licensee") accessing and otherwise using
+this software in source or binary form and its associated
+documentation ("the Software").
+
+2. Subject to the terms and conditions of this BeOpen Python License
+Agreement, BeOpen hereby grants Licensee a non-exclusive,
+royalty-free, world-wide license to reproduce, analyze, test, perform
+and/or display publicly, prepare derivative works, distribute, and
+otherwise use the Software alone or in any derivative version,
+provided, however, that the BeOpen Python License is retained in the
+Software, alone or in any derivative version prepared by Licensee.
+
+3. BeOpen is making the Software available to Licensee on an "AS IS"
+basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
+SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
+AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
+DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+5. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+6. This License Agreement shall be governed by and interpreted in all
+respects by the law of the State of California, excluding conflict of
+law provisions. Nothing in this License Agreement shall be deemed to
+create any relationship of agency, partnership, or joint venture
+between BeOpen and Licensee. This License Agreement does not grant
+permission to use BeOpen trademarks or trade names in a trademark
+sense to endorse or promote products or services of Licensee, or any
+third party. As an exception, the "BeOpen Python" logos available at
+http://www.pythonlabs.com/logos.html may be used according to the
+permissions granted on that web page.
+
+7. By copying, installing or otherwise using the software, Licensee
+agrees to be bound by the terms and conditions of this License
+Agreement.
+
+
+CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1
+---------------------------------------
+
+1. This LICENSE AGREEMENT is between the Corporation for National
+Research Initiatives, having an office at 1895 Preston White Drive,
+Reston, VA 20191 ("CNRI"), and the Individual or Organization
+("Licensee") accessing and otherwise using Python 1.6.1 software in
+source or binary form and its associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement, CNRI
+hereby grants Licensee a nonexclusive, royalty-free, world-wide
+license to reproduce, analyze, test, perform and/or display publicly,
+prepare derivative works, distribute, and otherwise use Python 1.6.1
+alone or in any derivative version, provided, however, that CNRI's
+License Agreement and CNRI's notice of copyright, i.e., "Copyright (c)
+1995-2001 Corporation for National Research Initiatives; All Rights
+Reserved" are retained in Python 1.6.1 alone or in any derivative
+version prepared by Licensee. Alternately, in lieu of CNRI's License
+Agreement, Licensee may substitute the following text (omitting the
+quotes): "Python 1.6.1 is made available subject to the terms and
+conditions in CNRI's License Agreement. This Agreement together with
+Python 1.6.1 may be located on the Internet using the following
+unique, persistent identifier (known as a handle): 1895.22/1013. This
+Agreement may also be obtained from a proxy server on the Internet
+using the following URL: http://hdl.handle.net/1895.22/1013".
+
+3. In the event Licensee prepares a derivative work that is based on
+or incorporates Python 1.6.1 or any part thereof, and wants to make
+the derivative work available to others as provided herein, then
+Licensee hereby agrees to include in any such work a brief summary of
+the changes made to Python 1.6.1.
+
+4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS"
+basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
+1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
+A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,
+OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+6. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+7. This License Agreement shall be governed by the federal
+intellectual property law of the United States, including without
+limitation the federal copyright law, and, to the extent such
+U.S. federal law does not apply, by the law of the Commonwealth of
+Virginia, excluding Virginia's conflict of law provisions.
+Notwithstanding the foregoing, with regard to derivative works based
+on Python 1.6.1 that incorporate non-separable material that was
+previously distributed under the GNU General Public License (GPL), the
+law of the Commonwealth of Virginia shall govern this License
+Agreement only as to issues arising under or with respect to
+Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this
+License Agreement shall be deemed to create any relationship of
+agency, partnership, or joint venture between CNRI and Licensee. This
+License Agreement does not grant permission to use CNRI trademarks or
+trade name in a trademark sense to endorse or promote products or
+services of Licensee, or any third party.
+
+8. By clicking on the "ACCEPT" button where indicated, or by copying,
+installing or otherwise using Python 1.6.1, Licensee agrees to be
+bound by the terms and conditions of this License Agreement.
+
+ ACCEPT
+
+
+CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2
+--------------------------------------------------
+
+Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,
+The Netherlands. All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/MANIFEST.in b/MANIFEST.in
index c80deb5..c43833b 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,3 +1,3 @@
-recursive-include dateutil *.py
+recursive-include dateutil *.py *.tar.*
include setup.py setup.cfg MANIFEST.in README LICENSE Makefile
include test.py
diff --git a/dateutil/tz.py b/dateutil/tz.py
index fcc14ef..da4a0c0 100644
--- a/dateutil/tz.py
+++ b/dateutil/tz.py
@@ -10,13 +10,22 @@ __license__ = "PSF License"
import datetime
import struct
import time
+import sys
+import os
relativedelta = None
parser = None
rrule = None
-__all__ = ["tzutc", "tzoffset", "tzlocal", "tzfile",
- "tzrange", "tzstr", "tzical", "gettz"]
+__all__ = ["tzutc", "tzoffset", "tzlocal", "tzfile", "tzrange",
+ "tzstr", "tzical", "tzwin", "gettz"]
+
+try:
+ import _winreg
+except ImportError:
+ tzwin = None
+else:
+ from dateutil.tzwin import tzwin
ZERO = datetime.timedelta(0)
EPOCHORDINAL = datetime.datetime.utcfromtimestamp(0).toordinal()
@@ -188,12 +197,12 @@ class tzfile(datetime.tzinfo):
def __init__(self, fileobj):
if isinstance(fileobj, basestring):
- self._s = fileobj
+ self._filename = fileobj
fileobj = open(fileobj)
elif hasattr(fileobj, "name"):
- self._s = fileobj.name
+ self._filename = fileobj.name
else:
- self._s = `fileobj`
+ self._filename = `fileobj`
# From tzfile(5):
#
@@ -453,9 +462,12 @@ class tzfile(datetime.tzinfo):
def __repr__(self):
- return "%s(%s)" % (self.__class__.__name__, `self._s`)
+ return "%s(%s)" % (self.__class__.__name__, `self._filename`)
- __reduce__ = object.__reduce__
+ def __reduce__(self):
+ if not os.path.isfile(self._filename):
+ raise ValueError, "Unpickable %s class" % self.__class__.__name__
+ return (self.__class__, (self._filename,))
class tzrange(datetime.tzinfo):
@@ -844,8 +856,6 @@ class tzical:
def __repr__(self):
return "%s(%s)" % (self.__class__.__name__, `self._s`)
-import sys, os
-
TZFILES = ["/etc/localtime", "localtime"]
TZPATHS = ["/usr/share/zoneinfo", "/usr/lib/zoneinfo", "/etc/zoneinfo"]
diff --git a/dateutil/tzwin.py b/dateutil/tzwin.py
new file mode 100644
index 0000000..1cb1bab
--- /dev/null
+++ b/dateutil/tzwin.py
@@ -0,0 +1,155 @@
+# This code was kindly provided by Jeffrey Harris.
+import _winreg
+import struct
+import datetime
+
+TIMEZONESKEY = r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones"
+TIMEZONEINFOKEY = r"SYSTEM\CurrentControlSet\Control\TimeZoneInformation"
+HANDLE = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
+LOCALKEY = _winreg.OpenKey(HANDLE, TIMEZONEINFOKEY)
+TZPARENT = _winreg.OpenKey(HANDLE, TIMEZONESKEY)
+TZPARENTSIZE = _winreg.QueryInfoKey(TZPARENT)[0]
+ONEWEEK = datetime.timedelta(7)
+
+class tzwin(datetime.tzinfo):
+ """tzinfo class based on win32's timezones available in the registry.
+
+ >>> local = tzwin('Central Standard Time')
+ >>> oct1 = datetime.datetime(month=10, year=2004, day=1, tzinfo=local)
+ >>> dec1 = datetime.datetime(month=12, year=2004, day=1, tzinfo=local)
+ >>> oct1.dst()
+ datetime.timedelta(0, 3600)
+ >>> dec1.dst()
+ datetime.timedelta(0)
+ >>> braz = tzwin('E. South America Standard Time')
+ >>> braz.dst(oct1)
+ datetime.timedelta(0)
+ >>> braz.dst(dec1)
+ datetime.timedelta(0, 3600)
+
+ """
+ def __init__(self, name):
+ self._info = _tzwininfo(name)
+
+ def utcoffset(self, dt):
+ if self._isdst(dt):
+ return datetime.timedelta(minutes=self._info.dstoffset)
+ else:
+ return datetime.timedelta(minutes=self._info.stdoffset)
+
+ def dst(self, dt):
+ if self._isdst(dt):
+ minutes = self._info.dstoffset - self._info.stdoffset
+ return datetime.timedelta(minutes=minutes)
+ else:
+ return datetime.timedelta(0)
+
+ def tzname(self, dt):
+ if self._isdst(dt):
+ return self._info.dstname
+ else:
+ return self._info.stdname
+
+ def list():
+ """Return a list of all time zones known to the system."""
+ return [_winreg.EnumKey(TZPARENT, i) for i in range(TZPARENTSIZE)]
+ list = staticmethod(list)
+
+ def _isdst(self, dt):
+ i = self._info
+ dston = picknthweekday(dt.year, i.dstmonth, i.dstdayofweek,
+ i.dsthour, i.dstminute, i.dstweeknumber)
+ dstoff = picknthweekday(dt.year, i.stdmonth, i.stddayofweek,
+ i.stdhour, i.stdminute, i.stdweeknumber)
+ if dston < dstoff:
+ return dston <= dt.replace(tzinfo=None) < dstoff
+ else:
+ return not dstoff <= dt.replace(tzinfo=None) < dston
+
+ def __repr__(self):
+ return "tzwin(%s)" % repr(self._info.display)
+
+ __reduce__ = object.__reduce__
+
+class _tzwininfo(object):
+ """Read a registry key for a timezone, expose its contents."""
+
+ def __init__(self, path):
+ """Load path, or if path is empty, load local time."""
+ if path:
+ keydict=valuestodict(_winreg.OpenKey(TZPARENT, path))
+ self.display = keydict['Display']
+ self.dstname = keydict['Dlt']
+ self.stdname = keydict['Std']
+
+ #see http://ww_winreg.jsiinc.com/SUBA/tip0300/rh0398.htm
+ tup = struct.unpack('=3l16h', keydict['TZI'])
+ self.stdoffset = -tup[0]-tup[1] #Bias + StandardBias * -1
+ self.dstoffset = self.stdoffset - tup[2] # + DaylightBias * -1
+
+ offset=3
+ self.stdmonth = tup[1 + offset]
+ self.stddayofweek = tup[2 + offset] #Sunday=0
+ self.stdweeknumber = tup[3 + offset] #Last = 5
+ self.stdhour = tup[4 + offset]
+ self.stdminute = tup[5 + offset]
+
+ offset=11
+ self.dstmonth = tup[1 + offset]
+ self.dstdayofweek = tup[2 + offset] #Sunday=0
+ self.dstweeknumber = tup[3 + offset] #Last = 5
+ self.dsthour = tup[4 + offset]
+ self.dstminute = tup[5 + offset]
+
+ else:
+ keydict=valuestodict(LOCALKEY)
+
+ self.stdname = keydict['StandardName']
+ self.dstname = keydict['DaylightName']
+
+ sourcekey=_winreg.OpenKey(TZPARENT, self.stdname)
+ self.display = valuestodict(sourcekey)['Display']
+
+ self.stdoffset = -keydict['Bias']-keydict['StandardBias']
+ self.dstoffset = self.stdoffset - keydict['DaylightBias']
+
+ #see http://ww_winreg.jsiinc.com/SUBA/tip0300/rh0398.htm
+ tup = struct.unpack('=8h', keydict['StandardStart'])
+
+ offset=0
+ self.stdmonth = tup[1 + offset]
+ self.stddayofweek = tup[2 + offset] #Sunday=0
+ self.stdweeknumber = tup[3 + offset] #Last = 5
+ self.stdhour = tup[4 + offset]
+ self.stdminute = tup[5 + offset]
+
+ tup = struct.unpack('=8h', keydict['DaylightStart'])
+ self.dstmonth = tup[1 + offset]
+ self.dstdayofweek = tup[2 + offset] #Sunday=0
+ self.dstweeknumber = tup[3 + offset] #Last = 5
+ self.dsthour = tup[4 + offset]
+ self.dstminute = tup[5 + offset]
+
+def picknthweekday(year, month, dayofweek, hour, minute, whichweek):
+ """dayofweek == 0 means Sunday, whichweek 5 means last instance"""
+ first = datetime.datetime(year, month, 1, hour, minute)
+ weekdayone = first.replace(day=((dayofweek-first.isoweekday())%7+1))
+ for n in xrange(whichweek):
+ dt = weekdayone+(whichweek-n)*ONEWEEK
+ if dt.month == month:
+ return dt
+
+def valuestodict(key):
+ """Convert a registry key's values to a dictionary."""
+ dict={}
+ size=_winreg.QueryInfoKey(key)[1]
+ for i in xrange(size):
+ dict[_winreg.EnumValue(key, i)[0]]=_winreg.EnumValue(key, i)[1]
+ return dict
+
+def _test():
+ import tzwin, doctest
+ doctest.testmod(tzwin, verbose=0)
+
+if __name__ == '__main__':
+ _test()
diff --git a/dateutil/zoneinfo/__init__.py b/dateutil/zoneinfo/__init__.py
index 8dfd118..73f2390 100644
--- a/dateutil/zoneinfo/__init__.py
+++ b/dateutil/zoneinfo/__init__.py
@@ -7,6 +7,10 @@ __all__ = ["setcachesize", "gettz", "rebuild"]
CACHE = []
CACHESIZE = 10
+class tzfile(tzfile):
+ def __reduce__(self):
+ return (gettz, (self._filename,))
+
ZONEINFOFILE = None
for entry in os.listdir(os.path.dirname(__file__)):
if entry.startswith("zoneinfo") and ".tar." in entry:
diff --git a/example.py b/example.py
new file mode 100644
index 0000000..f5a8e6f
--- /dev/null
+++ b/example.py
@@ -0,0 +1,15 @@
+from dateutil.relativedelta import *
+from dateutil.easter import *
+from dateutil.rrule import *
+from dateutil.parser import *
+from datetime import *
+import commands
+import os
+now = parse(commands.getoutput("date"))
+today = now.date()
+year = rrule(YEARLY,bymonth=8,bymonthday=13,byweekday=FR)[0].year
+rdelta = relativedelta(easter(year), today)
+print "Today is:", today
+print "Year with next Aug 13th on a Friday is:", year
+print "How far is the Easter of that year:", rdelta
+print "And the Easter of that year is:", today+rdelta
diff --git a/sandbox/scheduler.py b/sandbox/scheduler.py
new file mode 100644
index 0000000..681f442
--- /dev/null
+++ b/sandbox/scheduler.py
@@ -0,0 +1,157 @@
+"""
+Copyright (c) 2003 Gustavo Niemeyer <niemeyer@conectiva.com>
+
+This module offers extensions to the standard python 2.3+
+datetime module.
+"""
+__author__ = "Gustavo Niemeyer <niemeyer@conectiva.com>"
+__license__ = "PSF License"
+
+import datetime
+import thread
+import signal
+import time
+
+class sched:
+
+ def __init__(self, rrule,
+ tolerance=None, last=None,
+ execute=None, args=None, kwargs=None):
+ self._rrule = rrule
+ if tolerance:
+ self._tolerance = datetime.timedelta(seconds=tolerance)
+ else:
+ self._tolerance = None
+ self._last = last
+ self._execute = execute
+ self._args = args or ()
+ self._kwargs = kwargs or {}
+
+ def last(self):
+ return self._last
+
+ def next(self, now=None):
+ if not now:
+ now = datetime.datetime.now()
+ return self._rrule.after(now)
+
+ def check(self, now=None, readonly=False):
+ if not now:
+ now = datetime.datetime.now()
+ item = self._rrule.before(now, inc=True)
+ if (item is None or item == self._last or
+ (self._tolerance and item+self._tolerance < now)):
+ return None
+ if not readonly:
+ self._last = item
+ if self._execute:
+ self._execute(*self._args, **self._kwargs)
+ return item
+
+
+class schedset:
+ def __init__(self):
+ self._scheds = []
+
+ def add(self, sched):
+ self._scheds.append(sched)
+
+ def next(self, now=None):
+ if not now:
+ now = datetime.datetime.now()
+ res = None
+ for sched in self._scheds:
+ next = sched.next(now)
+ if next and (not res or next < res):
+ res = next
+ return res
+
+ def check(self, now=None, readonly=False):
+ if not now:
+ now = datetime.datetime.now()
+ res = False
+ for sched in self._scheds:
+ if sched.check(now, readonly):
+ res = True
+ return res
+
+
+class schedthread:
+
+ def __init__(self, sched, lock=None):
+ self._sched = sched
+ self._lock = lock
+ self._running = False
+
+ def running(self):
+ return self._running
+
+ def run(self):
+ self._running = True
+ thread.start_new_thread(self._loop, ())
+
+ def stop(self):
+ self._running = False
+
+ def _loop(self):
+ while self._running:
+ if self._lock:
+ self._lock.acquire()
+ now = datetime.datetime.now()
+ self._sched.check(now)
+ if self._lock:
+ self._lock.release()
+ seconds = _seconds_left(self._sched.next(now))
+ if seconds is None:
+ self._running = False
+ break
+ if self._running:
+ time.sleep(seconds)
+
+
+class schedalarm:
+
+ def __init__(self, sched, lock=None):
+ self._sched = sched
+ self._lock = lock
+ self._running = False
+
+ def running(self):
+ return self._running
+
+ def run(self):
+ self._running = True
+ signal.signal(signal.SIGALRM, self._handler)
+ self._handler(None, None)
+
+ def stop(self):
+ self._running = False
+
+ def _handler(self, sig, frame):
+ while self._running:
+ if self._lock:
+ self._lock.acquire()
+ now = datetime.datetime.now()
+ self._sched.check(now)
+ if self._lock:
+ self._lock.release()
+ if self._running:
+ seconds = _seconds_left(self._sched.next(now))
+ if seconds:
+ signal.alarm(seconds)
+ break
+ elif seconds is None:
+ self._running = False
+ break
+
+
+def _seconds_left(next):
+ if not next:
+ return None
+ now = datetime.datetime.now()
+ delta = next-now
+ seconds = delta.days*86400+delta.seconds
+ if seconds < 0:
+ seconds = 0
+ return seconds
+
diff --git a/setup.py b/setup.py
index bcf8029..d8067e9 100644
--- a/setup.py
+++ b/setup.py
@@ -1,5 +1,13 @@
#!/usr/bin/python
+from distutils.sysconfig import get_python_lib
from distutils.core import setup
+import glob
+import os
+
+if os.path.isfile("MANIFEST"):
+ os.unlink("MANIFEST")
+
+PYTHONLIB = get_python_lib(1)
setup(name="python-dateutil",
version = "0.5",
@@ -14,4 +22,6 @@ The dateutil module provides powerful extensions to the standard
datetime module, available in Python 2.3+.
""",
packages = ["dateutil"],
+ data_files = [(PYTHONLIB+"/dateutil/zoneinfo",
+ glob.glob("dateutil/zoneinfo/zoneinfo*.tar.*"))],
)