Skip to content

Commit

Permalink
Snapshot of python-dateutil-1.3
Browse files Browse the repository at this point in the history
  • Loading branch information
niemeyer authored and paxan committed Apr 2, 2009
1 parent 9ce0782 commit 7c5ea8a
Show file tree
Hide file tree
Showing 12 changed files with 105 additions and 54 deletions.
19 changes: 19 additions & 0 deletions NEWS
@@ -1,3 +1,22 @@
Version 1.3
-----------

- Fixed precision problem on conversion of decimal seconds to
microseconds, as reported by Skip Montanaro.

- Fixed bug in constructor of parser, and converted parser classes to
new-style classes. Original report and patch by Michael Elsd�rfer.

- Initialize tzid and comps in tz.py, to prevent the code from ever
raising a NameError (even with broken files). Johan Dahlin suggested
the fix after a pyflakes run.

- Version is now published in dateutil.__version__, as requested
by Darren Dale.

- All code is compatible with new-style division.


Version 1.2
-----------

Expand Down
2 changes: 1 addition & 1 deletion PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: python-dateutil
Version: 1.2
Version: 1.3
Summary: Extensions to the standard python 2.3+ datetime module
Home-page: http://labix.org/python-dateutil
Author: Gustavo Niemeyer
Expand Down
3 changes: 2 additions & 1 deletion dateutil/__init__.py
@@ -1,8 +1,9 @@
"""
Copyright (c) 2003-2005 Gustavo Niemeyer <gustavo@niemeyer.net>
Copyright (c) 2003-2007 Gustavo Niemeyer <gustavo@niemeyer.net>
This module offers extensions to the standard python 2.3+
datetime module.
"""
__author__ = "Gustavo Niemeyer <gustavo@niemeyer.net>"
__license__ = "PSF License"
__version__ = "1.3"
20 changes: 10 additions & 10 deletions dateutil/easter.py
@@ -1,5 +1,5 @@
"""
Copyright (c) 2003-2005 Gustavo Niemeyer <gustavo@niemeyer.net>
Copyright (c) 2003-2007 Gustavo Niemeyer <gustavo@niemeyer.net>
This module offers extensions to the standard python 2.3+
datetime module.
Expand Down Expand Up @@ -70,23 +70,23 @@ def easter(year, method=EASTER_WESTERN):
if method < 3:
# Old method
i = (19*g+15)%30
j = (y+y/4+i)%7
j = (y+y//4+i)%7
if method == 2:
# Extra dates to convert Julian to Gregorian date
e = 10
if y > 1600:
e = e+y/100-16-(y/100-16)/4
e = e+y//100-16-(y//100-16)//4
else:
# New method
c = y/100
h = (c-c/4-(8*c+13)/25+19*g+15)%30
i = h-(h/28)*(1-(h/28)*(29/(h+1))*((21-g)/11))
j = (y+y/4+i+2-c+c/4)%7
c = y//100
h = (c-c//4-(8*c+13)//25+19*g+15)%30
i = h-(h//28)*(1-(h//28)*(29//(h+1))*((21-g)//11))
j = (y+y//4+i+2-c+c//4)%7

# p can be from -6 to 56 corresponding to dates 22 March to 23 May
# (later dates apply to method 2, although 23 May never actually occurs)
p = i-j+e
d = 1+(p+27+(p+6)/40)%31
m = 3+(p+26)/30
return datetime.date(y,m,d)
d = 1+(p+27+(p+6)//40)%31
m = 3+(p+26)//30
return datetime.date(int(y),int(m),int(d))

60 changes: 31 additions & 29 deletions dateutil/parser.py
@@ -1,24 +1,31 @@
# -*- coding:iso-8859-1 -*-
"""
Copyright (c) 2003-2005 Gustavo Niemeyer <gustavo@niemeyer.net>
Copyright (c) 2003-2007 Gustavo Niemeyer <gustavo@niemeyer.net>
This module offers extensions to the standard python 2.3+
datetime module.
"""
__author__ = "Gustavo Niemeyer <gustavo@niemeyer.net>"
__license__ = "PSF License"

import os.path
import datetime
import string
import sys
import time
import sys
import os

try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO

import datetime
import relativedelta
import tz


__all__ = ["parse", "parserinfo"]


# Some pointers:
#
# http://www.cl.cam.ac.uk/~mgk25/iso-time.html
Expand All @@ -28,12 +35,9 @@
# http://search.cpan.org/author/MUIR/Time-modules-2003.0211/lib/Time/ParseDate.pm
# http://stein.cshl.org/jade/distrib/docs/java.text.SimpleDateFormat.html

try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO

class _timelex:
class _timelex(object):

def __init__(self, instream):
if isinstance(instream, basestring):
instream = StringIO(instream)
Expand Down Expand Up @@ -139,6 +143,7 @@ def split(cls, s):
return list(cls(s))
split = classmethod(split)


class _resultbase(object):

def __init__(self):
Expand All @@ -156,7 +161,8 @@ def _repr(self, classname):
def __repr__(self):
return self._repr(self.__class__.__name__)

class parserinfo:

class parserinfo(object):

# m from a.m/p.m, t from ISO T separator
JUMP = [" ", ".", ",", ";", "-", "/", "'",
Expand Down Expand Up @@ -204,7 +210,7 @@ def __init__(self, dayfirst=False, yearfirst=False):
self.yearfirst = yearfirst

self._year = time.localtime().tm_year
self._century = self._year/100*100
self._century = self._year//100*100

def _convert(self, lst):
dct = {}
Expand Down Expand Up @@ -281,15 +287,10 @@ def validate(self, res):
return True


class parser:
class parser(object):

def __init__(self, info=parserinfo):
if issubclass(info, parserinfo):
self.info = parserinfo()
elif isinstance(info, parserinfo):
self.info = info
else:
raise TypeError, "Unsupported parserinfo type"
def __init__(self, info=None):
self.info = info or parserinfo()

def parse(self, timestr, default=None,
ignoretz=False, tzinfos=None,
Expand Down Expand Up @@ -387,9 +388,7 @@ def _parse(self, timestr, dayfirst=None, yearfirst=None, fuzzy=False):
res.hour = int(s[:2])
res.minute = int(s[2:4])
value = float(s[4:])
res.second = int(value)
if value%1:
res.microsecond = int(1000000*(value%1))
res.second, res.microsecond = _parsems(value)
elif len_li == 8:
# YYYYMMDD
s = l[i-1]
Expand Down Expand Up @@ -423,9 +422,7 @@ def _parse(self, timestr, dayfirst=None, yearfirst=None, fuzzy=False):
if value%1:
res.second = int(60*(value%1))
elif idx == 2:
res.second = int(value)
if value%1:
res.microsecond = int(1000000*(value%1))
res.second, res.microsecond = _parsems(value)
i += 1
if i >= len_l or idx == 2:
break
Expand All @@ -452,9 +449,7 @@ def _parse(self, timestr, dayfirst=None, yearfirst=None, fuzzy=False):
i += 1
if i < len_l and l[i] == ':':
value = float(l[i+1])
res.second = int(value)
if value%1:
res.microsecond = int(1000000*(value%1))
res.second, res.microsecond = _parsems(value)
i += 2
elif i < len_l and l[i] in ('-', '/', '.'):
sep = l[i]
Expand Down Expand Up @@ -699,7 +694,8 @@ def parse(timestr, parserinfo=None, **kwargs):
else:
return DEFAULTPARSER.parse(timestr, **kwargs)

class _tzparser:

class _tzparser(object):

class _result(_resultbase):

Expand Down Expand Up @@ -868,8 +864,14 @@ def parse(self, tzstr):

return res


DEFAULTTZPARSER = _tzparser()
def _parsetz(tzstr):
return DEFAULTTZPARSER.parse(tzstr)


def _parsems(value):
return int(value), int(value * 1000000) - int(value) * 1000000


# vim:ts=4:sw=4:et
14 changes: 7 additions & 7 deletions dateutil/relativedelta.py
@@ -1,5 +1,5 @@
"""
Copyright (c) 2003-2005 Gustavo Niemeyer <gustavo@niemeyer.net>
Copyright (c) 2003-2007 Gustavo Niemeyer <gustavo@niemeyer.net>
This module offers extensions to the standard python 2.3+
datetime module.
Expand Down Expand Up @@ -201,27 +201,27 @@ def __init__(self, dt1=None, dt2=None,

def _fix(self):
if abs(self.microseconds) > 999999:
s = self.microseconds/abs(self.microseconds)
s = self.microseconds//abs(self.microseconds)
div, mod = divmod(self.microseconds*s, 1000000)
self.microseconds = mod*s
self.seconds += div*s
if abs(self.seconds) > 59:
s = self.seconds/abs(self.seconds)
s = self.seconds//abs(self.seconds)
div, mod = divmod(self.seconds*s, 60)
self.seconds = mod*s
self.minutes += div*s
if abs(self.minutes) > 59:
s = self.minutes/abs(self.minutes)
s = self.minutes//abs(self.minutes)
div, mod = divmod(self.minutes*s, 60)
self.minutes = mod*s
self.hours += div*s
if abs(self.hours) > 23:
s = self.hours/abs(self.hours)
s = self.hours//abs(self.hours)
div, mod = divmod(self.hours*s, 24)
self.hours = mod*s
self.days += div*s
if abs(self.months) > 11:
s = self.months/abs(self.months)
s = self.months//abs(self.months)
div, mod = divmod(self.months*s, 12)
self.months = mod*s
self.years += div*s
Expand All @@ -235,7 +235,7 @@ def _fix(self):
def _set_months(self, months):
self.months = months
if abs(self.months) > 11:
s = self.months/abs(self.months)
s = self.months//abs(self.months)
div, mod = divmod(self.months*s, 12)
self.months = mod*s
self.years = div*s
Expand Down
2 changes: 1 addition & 1 deletion dateutil/rrule.py
@@ -1,5 +1,5 @@
"""
Copyright (c) 2003-2005 Gustavo Niemeyer <gustavo@niemeyer.net>
Copyright (c) 2003-2007 Gustavo Niemeyer <gustavo@niemeyer.net>
This module offers extensions to the standard python 2.3+
datetime module.
Expand Down
4 changes: 3 additions & 1 deletion dateutil/tz.py
@@ -1,5 +1,5 @@
"""
Copyright (c) 2003-2005 Gustavo Niemeyer <gustavo@niemeyer.net>
Copyright (c) 2003-2007 Gustavo Niemeyer <gustavo@niemeyer.net>
This module offers extensions to the standard python 2.3+
datetime module.
Expand Down Expand Up @@ -753,6 +753,8 @@ def _parse_rfc(self, s):
else:
i += 1

tzid = None
comps = []
invtz = False
comptype = None
for line in lines:
Expand Down
Binary file removed dateutil/zoneinfo/zoneinfo-2007f.tar.gz
Binary file not shown.
Binary file added dateutil/zoneinfo/zoneinfo-2007i.tar.gz
Binary file not shown.
9 changes: 8 additions & 1 deletion setup.py
Expand Up @@ -4,16 +4,23 @@
from os.path import isfile, join
import glob
import os
import re


if isfile("MANIFEST"):
os.unlink("MANIFEST")


# Get PYTHONLIB with no prefix so --prefix installs work.
PYTHONLIB = join(get_python_lib(standard_lib=1, prefix=''), 'site-packages')
ZONEINFO = join("dateutil", "zoneinfo")

VERSION = re.search('__version__ = "([^"]+)"',
open("dateutil/__init__.py").read()).group(1)


setup(name="python-dateutil",
version = "1.2",
version = VERSION,
description = "Extensions to the standard python 2.3+ datetime module",
author = "Gustavo Niemeyer",
author_email = "gustavo@niemeyer.net",
Expand Down
26 changes: 23 additions & 3 deletions test.py
@@ -1,6 +1,9 @@
#!/usr/bin/python
import unittest
# -*- encoding: utf-8 -*-
from cStringIO import StringIO
import unittest
import calendar
import time
import base64
import os

Expand All @@ -21,8 +24,6 @@

from datetime import *

import calendar
import time

class RelativeDeltaTest(unittest.TestCase):
now = datetime(2003, 9, 17, 20, 54, 47, 282310)
Expand Down Expand Up @@ -2949,6 +2950,7 @@ def testBadBySetPosMany(self):


class ParserTest(unittest.TestCase):

def setUp(self):
self.tzinfos = {"BRST": -10800}
self.brsttz = tzoffset("BRST", -10800)
Expand Down Expand Up @@ -3548,6 +3550,24 @@ def testIncreasingISOFormat(self):
self.assertEqual(parse(dt.isoformat()), dt)
dt += delta

def testMicrosecondsPrecisionError(self):
# Skip found out that sad precision problem. :-(
dt1 = parse("00:11:25.01")
dt2 = parse("00:12:10.01")
self.assertEquals(dt1.microsecond, 10000)
self.assertEquals(dt2.microsecond, 10000)

def testCustomParserInfo(self):
# Custom parser info wasn't working, as Michael Elsdörfer discovered.
from dateutil.parser import parserinfo, parser
class myparserinfo(parserinfo):
MONTHS = parserinfo.MONTHS[:]
MONTHS[0] = ("Foo", "Foo")
myparser = parser(myparserinfo())
dt = myparser.parse("01/Foo/2007")
self.assertEquals(dt, datetime(2007, 1, 1))


class EasterTest(unittest.TestCase):
easterlist = [
# WESTERN ORTHODOX
Expand Down

0 comments on commit 7c5ea8a

Please sign in to comment.