[Python-modules-commits] [isodate] 17/22: Imported Upstream version 0.5.0

Maximiliano Curia maxy at moszumanska.debian.org
Wed Sep 10 19:21:08 UTC 2014


This is an automated email from the git hooks/post-receive script.

maxy pushed a commit to branch master
in repository isodate.

commit d05ab9a89416adee8d3362c784271a894ec2eca9
Author: Maximiliano Curia <maxy at gnuservers.com.ar>
Date:   Wed Sep 10 11:55:57 2014 +0200

    Imported Upstream version 0.5.0
---
 .hg_archival.txt                          |   5 -
 .hgignore                                 |  12 --
 .hgtags                                   |   4 -
 .project                                  |  17 ---
 CHANGES.txt                               |  31 ++++
 PKG-INFO                                  | 242 ++++++++++++++++++++++++++++++
 README.txt => README.rst                  |   5 +-
 bootstrap.py                              |  62 --------
 buildout.cfg                              |  32 ----
 setup.cfg                                 |   5 +
 setup.py                                  |  30 ++--
 src/isodate.egg-info/PKG-INFO             | 242 ++++++++++++++++++++++++++++++
 src/isodate.egg-info/SOURCES.txt          |  26 ++++
 src/isodate.egg-info/dependency_links.txt |   1 +
 src/isodate.egg-info/top_level.txt        |   1 +
 src/isodate/duration.py                   |  23 ++-
 src/isodate/isoduration.py                |   7 +-
 src/isodate/isoerror.py                   |   2 +-
 src/isodate/isostrf.py                    |  10 +-
 src/isodate/isotime.py                    |   9 +-
 src/isodate/isotzinfo.py                  |  11 +-
 src/isodate/tests/__init__.py             |  12 +-
 src/isodate/tests/test_date.py            |   4 +
 src/isodate/tests/test_datetime.py        |  54 +++++--
 src/isodate/tests/test_duration.py        |  68 +++++++--
 src/isodate/tests/test_pickle.py          |  35 +++++
 src/isodate/tests/test_strf.py            | 130 ++++++++++++++++
 src/isodate/tests/test_time.py            |   4 +
 src/isodate/tzinfo.py                     |  28 ++--
 29 files changed, 901 insertions(+), 211 deletions(-)

diff --git a/.hg_archival.txt b/.hg_archival.txt
deleted file mode 100644
index 34d0e69..0000000
--- a/.hg_archival.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-repo: b8b3628077e2d5fc513caa08b3e7aa1254fd79c4
-node: 8e37a5ab1100234ff09d3bf8960616a2b2a1cd61
-branch: default
-latesttag: RELEASE-0.4.6
-latesttagdistance: 1
diff --git a/.hgignore b/.hgignore
deleted file mode 100644
index c72a241..0000000
--- a/.hgignore
+++ /dev/null
@@ -1,12 +0,0 @@
-syntax: glob
-*.pyc
-isodate.egg-info
-build/
-.installed.cfg
-.pydevproject
-.settings
-bin
-develop-eggs
-dist
-parts
-MANIFEST
\ No newline at end of file
diff --git a/.hgtags b/.hgtags
deleted file mode 100644
index 83cb7ef..0000000
--- a/.hgtags
+++ /dev/null
@@ -1,4 +0,0 @@
-e6cd4b2e543e37ed278321374b63c41c3b4e9e68 RELEASE-0.3.0
-010c27908bd8ba7b0c1564abc7840d962f700812 RELEASE-0.4.0
-2b6b173b7feb80eb49e06c828d64e381aca17756 RELEASE-0.4.5
-22cb3855ca1e55931d5c0a3cf7b070f2475963b7 RELEASE-0.4.6
diff --git a/.project b/.project
deleted file mode 100644
index b4db36c..0000000
--- a/.project
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>isodate</name>
-	<comment></comment>
-	<projects>
-	</projects>
-	<buildSpec>
-		<buildCommand>
-			<name>org.python.pydev.PyDevBuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-	</buildSpec>
-	<natures>
-		<nature>org.python.pydev.pythonNature</nature>
-	</natures>
-</projectDescription>
diff --git a/CHANGES.txt b/CHANGES.txt
index cb1a7a0..ed60495 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -2,6 +2,37 @@
 CHANGES
 =======
 
+0.5.0 (2014-02-23)
+------------------
+
+- ISO8601Error are subclasses of ValueError now
+- improve compatibility across various python variants and versions
+- raise exceptions when using fractional years and months in date
+  maths with durations
+- renamed method todatetime on Duraction objects to totimedelta
+
+
+0.4.9 (2012-10-30)
+------------------
+
+- support pickling FixedOffset instances
+- make sure parsed fractional seconds are in microseconds
+- add leading zeros when formattig microseconds (Jarom Loveridge)
+
+
+0.4.8 (2012-05-04)
+------------------
+
+- fixed incompatibility of unittests with python 2.5 and 2.6 (runs fine on 2.7
+  and 3.2)
+
+
+0.4.7 (2012-01-26)
+------------------
+
+- fixed tzinfo formatting (never pass None into tzinfo.utcoffset())
+
+
 0.4.6 (2012-01-06)
 ------------------
 
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..e487953
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,242 @@
+Metadata-Version: 1.1
+Name: isodate
+Version: 0.5.0
+Summary: An ISO 8601 date/time/duration parser and formater
+Home-page: http://cheeseshop.python.org/pypi/isodate
+Author: Gerhard Weis
+Author-email: gerhard.weis at proclos.com
+License: BSD
+Description: 
+        ISO 8601 date/time parser
+        =========================
+        
+        .. image:: https://travis-ci.org/gweis/isodate.png?branch=master   :target: https://travis-ci.org/gweis/isodate
+        
+        This module implements ISO 8601 date, time and duration parsing.
+        The implementation follows ISO8601:2004 standard, and implements only
+        date/time representations mentioned in the standard. If something is not
+        mentioned there, then it is treated as non existent, and not as an allowed
+        option.
+        
+        For instance, ISO8601:2004 never mentions 2 digit years. So, it is not
+        intended by this module to support 2 digit years. (while it may still
+        be valid as ISO date, because it is not explicitly forbidden.)
+        Another example is, when no time zone information is given for a time,
+        then it should be interpreted as local time, and not UTC.
+        
+        As this module maps ISO 8601 dates/times to standard Python data types, like
+        *date*, *time*, *datetime* and *timedelta*, it is not possible to convert
+        all possible ISO 8601 dates/times. For instance, dates before 0001-01-01 are
+        not allowed by the Python *date* and *datetime* classes. Additionally
+        fractional seconds are limited to microseconds. That means if the parser finds
+        for instance nanoseconds it will round it to microseconds.
+        
+        Documentation
+        -------------
+        
+        Currently there are four parsing methods available.
+           * parse_time:
+                parses an ISO 8601 time string into a *time* object
+           * parse_date:
+                parses an ISO 8601 date string into a *date* object
+           * parse_datetime:
+                parses an ISO 8601 date-time string into a *datetime* object
+           * parse_duration:
+                parses an ISO 8601 duration string into a *timedelta* or *Duration*
+                object.
+           * parse_tzinfo:
+                parses the time zone info part of an ISO 8601 string into a
+                *tzinfo* object.
+        
+        As ISO 8601 allows to define durations in years and months, and *timedelta*
+        does not handle years and months, this module provides a *Duration* class,
+        which can be used almost like a *timedelta* object (with some limitations).
+        However, a *Duration* object can be converted into a *timedelta* object.
+        
+        There are also ISO formating methods for all supported data types. Each
+        *xxx_isoformat* method accepts a format parameter. The default format is
+        always the ISO 8601 expanded format. This is the same format used by
+        *datetime.isoformat*:
+        
+            * time_isoformat:
+                Intended to create ISO time strings with default format
+                *hh:mm:ssZ*.
+            * date_isoformat:
+                Intended to create ISO date strings with default format
+                *yyyy-mm-dd*.
+            * datetime_isoformat:
+                Intended to create ISO date-time strings with default format
+                *yyyy-mm-ddThh:mm:ssZ*.
+            * duration_isoformat:
+                Intended to create ISO duration strings with default format
+                *PnnYnnMnnDTnnHnnMnnS*.
+            * tz_isoformat:
+                Intended to create ISO time zone strings with default format
+                *hh:mm*.
+            * strftime:
+                A re-implementation mostly compatible with Python's *strftime*, but
+                supports only those format strings, which can also be used for dates
+                prior 1900. This method also understands how to format *datetime* and
+                *Duration* instances.
+        
+        Installation:
+        -------------
+        
+        This module can easily be installed with Python standard installation methods.
+        
+        Either use *python setup.py install* or in case you have *setuptools* or
+        *distribute* available, you can also use *easy_install*.
+        
+        Limitations:
+        ------------
+        
+           * The parser accepts several date/time representation which should be invalid
+             according to ISO 8601 standard.
+        
+             1. for date and time together, this parser accepts a mixture of basic and extended format.
+                e.g. the date could be in basic format, while the time is accepted in extended format.
+                It also allows short dates and times in date-time strings.
+             2. For incomplete dates, the first day is chosen. e.g. 19th century results in a date of
+                1901-01-01.
+             3. negative *Duration* and *timedelta* value are not fully supported yet.
+        
+        Further information:
+        --------------------
+        
+        The doc strings and unit tests should provide rather detailed information about
+        the methods and their limitations.
+        
+        The source release provides a *setup.py* script and a *buildout.cfg*. Both can
+        be used to run the unit tests included.
+        
+        Source code is available at `<http://github.com/gweis/isodate>`_.
+        
+        CHANGES
+        =======
+        
+        0.5.0 (2014-02-23)
+        ------------------
+        
+        - ISO8601Error are subclasses of ValueError now
+        - improve compatibility across various python variants and versions
+        - raise exceptions when using fractional years and months in date
+          maths with durations
+        - renamed method todatetime on Duraction objects to totimedelta
+        
+        
+        0.4.9 (2012-10-30)
+        ------------------
+        
+        - support pickling FixedOffset instances
+        - make sure parsed fractional seconds are in microseconds
+        - add leading zeros when formattig microseconds (Jarom Loveridge)
+        
+        
+        0.4.8 (2012-05-04)
+        ------------------
+        
+        - fixed incompatibility of unittests with python 2.5 and 2.6 (runs fine on 2.7
+          and 3.2)
+        
+        
+        0.4.7 (2012-01-26)
+        ------------------
+        
+        - fixed tzinfo formatting (never pass None into tzinfo.utcoffset())
+        
+        
+        0.4.6 (2012-01-06)
+        ------------------
+        
+        - added Python 3 compatibility via 2to3
+        
+        0.4.5 (2012-01-06)
+        ------------------
+        
+        - made setuptools dependency optional
+        
+        0.4.4 (2011-04-16)
+        ------------------
+        
+        - Fixed formatting of microseconds for datetime objects
+        
+        0.4.3 (2010-10-29)
+        ------------------
+        
+        - Fixed problem with %P formating and fractions (supplied by David Brooks)
+        
+        0.4.2 (2010-10-28)
+        ------------------
+        
+        - Implemented unary - for Duration (supplied by David Brooks)
+        - Output fractional seconds with '%P' format. (partly supplied by David Brooks)
+        
+        0.4.1 (2010-10-13)
+        ------------------
+        
+        - fixed bug in comparison between timedelta and Duration.
+        - fixed precision problem with microseconds (reported by Tommi Virtanen)
+        
+        0.4.0 (2009-02-09)
+        ------------------
+        
+        - added method to parse ISO 8601 time zone strings
+        - added methods to create ISO 8601 conforming strings
+        
+        0.3.0 (2009-1-05)
+        ------------------
+        
+        - Initial release
+        
+        TODOs
+        =====
+        
+        This to do list contains some thoughts and ideas about missing features, and
+        parts to think about, whether to implement them or not. This list is probably
+        not complete.
+        
+        Missing features:
+        -----------------
+        
+            * time formating does not allow to create fractional representations.
+            * parser for ISO intervals.
+            * currently microseconds are always padded to a length of 6 characters.
+              trailing 0s should be optional
+        
+        Documentation:
+        --------------
+        
+            * parse_datetime:
+               - complete documentation to show what this function allows, but ISO forbids.
+                 and vice verse.
+               - support other separators between date and time than 'T'
+        
+            * parse_date:
+               - yeardigits should be always greater than 4
+               - dates before 0001-01-01 are not supported
+        
+            * parse_duration:
+               - alternative formats are not fully supported due to parse_date restrictions
+               - standard duration format is fully supported but not very restrictive.
+        
+            * Duration:
+               - support fractional years and month in calculations
+               - implement w3c order relation? (`<http://www.w3.org/TR/xmlschema-2/#duration-order>`_)
+               - refactor to have duration mathematics only at one place.
+               - localize __str__ method (does timedelta do this?)
+               - when is a Duration negative?
+               - normalize Durations. months [00-12] and years ]-inf,+inf[
+        
+Platform: UNKNOWN
+Classifier: Development Status :: 4 - Beta
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3.2
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: Implementation :: PyPy
+Classifier: Topic :: Internet
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
diff --git a/README.txt b/README.rst
similarity index 95%
rename from README.txt
rename to README.rst
index 9c789c2..81fb196 100644
--- a/README.txt
+++ b/README.rst
@@ -2,6 +2,8 @@
 ISO 8601 date/time parser
 =========================
 
+.. image:: https://travis-ci.org/gweis/isodate.png?branch=master   :target: https://travis-ci.org/gweis/isodate
+
 This module implements ISO 8601 date, time and duration parsing.
 The implementation follows ISO8601:2004 standard, and implements only
 date/time representations mentioned in the standard. If something is not
@@ -99,5 +101,4 @@ the methods and their limitations.
 The source release provides a *setup.py* script and a *buildout.cfg*. Both can
 be used to run the unit tests included.
 
-Source code is available at `<http://hg.proclos.com/isodate>`_.
-
+Source code is available at `<http://github.com/gweis/isodate>`_.
diff --git a/bootstrap.py b/bootstrap.py
deleted file mode 100644
index 8cb88a1..0000000
--- a/bootstrap.py
+++ /dev/null
@@ -1,62 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2006 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Bootstrap a buildout-based project
-
-Simply run this script in a directory containing a buildout.cfg.
-The script accepts buildout command-line options, so you can
-use the -c option to specify an alternate configuration file.
-
-$Id$
-"""
-
-import os, shutil, sys, tempfile, urllib2
-
-tmpeggs = tempfile.mkdtemp()
-
-try:
-    import pkg_resources
-except ImportError:
-    ez = {}
-    exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
-                         ).read() in ez
-    ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
-
-    import pkg_resources
-
-if sys.platform == 'win32':
-    def quote(c):
-        if ' ' in c:
-            return '"%s"' % c # work around spawn lamosity on windows
-        else:
-            return c
-else:
-    def quote (c):
-        return c
-
-cmd = 'from setuptools.command.easy_install import main; main()'
-ws  = pkg_resources.working_set
-assert os.spawnle(
-    os.P_WAIT, sys.executable, quote (sys.executable),
-    '-c', quote (cmd), '-mqNxd', quote (tmpeggs), 'zc.buildout',
-    dict(os.environ,
-         PYTHONPATH=
-         ws.find(pkg_resources.Requirement.parse('setuptools')).location
-         ),
-    ) == 0
-
-ws.add_entry(tmpeggs)
-ws.require('zc.buildout')
-import zc.buildout.buildout
-zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
-shutil.rmtree(tmpeggs)
diff --git a/buildout.cfg b/buildout.cfg
deleted file mode 100644
index 5f8c446..0000000
--- a/buildout.cfg
+++ /dev/null
@@ -1,32 +0,0 @@
-[buildout]
-develop = .
-parts = isodate importchecker test pydev coverage coverage-report
-
-[isodate]
-recipe = zc.recipe.egg
-eggs = isodate
-interpreter = python
-
-[pydev]
-recipe = pb.recipes.pydev
-eggs = ${isodate:eggs}
-
-[test]
-recipe = zc.recipe.testrunner
-eggs = isodate
-
-[coverage]
-recipe = zc.recipe.testrunner
-eggs = isodate
-defaults = ['--coverage', '.'] 
-
-[coverage-report]
-recipe = zc.recipe.egg
-eggs = z3c.coverage
-scripts = coverage=coverage-report
-arguments = ('parts/coverage', 'parts/coverage-report')
-
-[importchecker]
-recipe = zc.recipe.egg
-eggs = importchecker
-arguments = "${buildout:directory}/src"
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..72f9d44
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,5 @@
+[egg_info]
+tag_svn_revision = 0
+tag_date = 0
+tag_build = 
+
diff --git a/setup.py b/setup.py
index 21e5418..7080a54 100644
--- a/setup.py
+++ b/setup.py
@@ -26,28 +26,27 @@
 # CONTRACT, STRICT LIABILITY, OR TORT
 ##############################################################################
 import os
+import sys
 
 setupargs = {}
 
 try:
-    from distutils.command.build_py import build_py_2to3 as build_py
-except ImportError:
-    # 2.x
-    from distutils.command.build_py import build_py
-
-try:
     from setuptools import setup
     setupargs['test_suite'] = 'isodate.tests.test_suite'
-    setupargs['use_2to3'] = True
+    if sys.version[0] == '3':
+        setupargs['use_2to3'] = True
 except ImportError:
     from distutils.core import setup
-    setupargs['cmdclass'] = {'build_py': build_py}
+    if sys.version[0] == '3':
+        from distutils.command.build_py import build_py_2to3
+        setupargs['cmdclass'] = {'build_py': build_py_2to3}
+
 
 def read(*rnames):
     return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
 
 setup(name='isodate',
-      version='0.4.6',
+      version='0.5.0',
       packages=['isodate', 'isodate.tests'],
       package_dir={'': 'src'},
 
@@ -62,9 +61,9 @@ setup(name='isodate',
       #keywords = '',
       url='http://cheeseshop.python.org/pypi/isodate',
 
-      long_description=read('README.txt') +
-                       read('CHANGES.txt') +
-                       read('TODO.txt'),
+      long_description=(read('README.rst') +
+                        read('CHANGES.txt') +
+                        read('TODO.txt')),
 
       classifiers=['Development Status :: 4 - Beta',
                    # 'Environment :: Web Environment',
@@ -72,8 +71,11 @@ setup(name='isodate',
                    'License :: OSI Approved :: BSD License',
                    'Operating System :: OS Independent',
                    'Programming Language :: Python',
-                   'Programming Language :: Python :: 2',
-                   'Programming Language :: Python :: 3',
+                   'Programming Language :: Python :: 2.6',
+                   'Programming Language :: Python :: 2.7',
+                   'Programming Language :: Python :: 3.2',
+                   'Programming Language :: Python :: 3.3',
+                   'Programming Language :: Python :: Implementation :: PyPy',
                    'Topic :: Internet',
                    'Topic :: Software Development :: Libraries :: Python Modules',
                    ],
diff --git a/src/isodate.egg-info/PKG-INFO b/src/isodate.egg-info/PKG-INFO
new file mode 100644
index 0000000..e487953
--- /dev/null
+++ b/src/isodate.egg-info/PKG-INFO
@@ -0,0 +1,242 @@
+Metadata-Version: 1.1
+Name: isodate
+Version: 0.5.0
+Summary: An ISO 8601 date/time/duration parser and formater
+Home-page: http://cheeseshop.python.org/pypi/isodate
+Author: Gerhard Weis
+Author-email: gerhard.weis at proclos.com
+License: BSD
+Description: 
+        ISO 8601 date/time parser
+        =========================
+        
+        .. image:: https://travis-ci.org/gweis/isodate.png?branch=master   :target: https://travis-ci.org/gweis/isodate
+        
+        This module implements ISO 8601 date, time and duration parsing.
+        The implementation follows ISO8601:2004 standard, and implements only
+        date/time representations mentioned in the standard. If something is not
+        mentioned there, then it is treated as non existent, and not as an allowed
+        option.
+        
+        For instance, ISO8601:2004 never mentions 2 digit years. So, it is not
+        intended by this module to support 2 digit years. (while it may still
+        be valid as ISO date, because it is not explicitly forbidden.)
+        Another example is, when no time zone information is given for a time,
+        then it should be interpreted as local time, and not UTC.
+        
+        As this module maps ISO 8601 dates/times to standard Python data types, like
+        *date*, *time*, *datetime* and *timedelta*, it is not possible to convert
+        all possible ISO 8601 dates/times. For instance, dates before 0001-01-01 are
+        not allowed by the Python *date* and *datetime* classes. Additionally
+        fractional seconds are limited to microseconds. That means if the parser finds
+        for instance nanoseconds it will round it to microseconds.
+        
+        Documentation
+        -------------
+        
+        Currently there are four parsing methods available.
+           * parse_time:
+                parses an ISO 8601 time string into a *time* object
+           * parse_date:
+                parses an ISO 8601 date string into a *date* object
+           * parse_datetime:
+                parses an ISO 8601 date-time string into a *datetime* object
+           * parse_duration:
+                parses an ISO 8601 duration string into a *timedelta* or *Duration*
+                object.
+           * parse_tzinfo:
+                parses the time zone info part of an ISO 8601 string into a
+                *tzinfo* object.
+        
+        As ISO 8601 allows to define durations in years and months, and *timedelta*
+        does not handle years and months, this module provides a *Duration* class,
+        which can be used almost like a *timedelta* object (with some limitations).
+        However, a *Duration* object can be converted into a *timedelta* object.
+        
+        There are also ISO formating methods for all supported data types. Each
+        *xxx_isoformat* method accepts a format parameter. The default format is
+        always the ISO 8601 expanded format. This is the same format used by
+        *datetime.isoformat*:
+        
+            * time_isoformat:
+                Intended to create ISO time strings with default format
+                *hh:mm:ssZ*.
+            * date_isoformat:
+                Intended to create ISO date strings with default format
+                *yyyy-mm-dd*.
+            * datetime_isoformat:
+                Intended to create ISO date-time strings with default format
+                *yyyy-mm-ddThh:mm:ssZ*.
+            * duration_isoformat:
+                Intended to create ISO duration strings with default format
+                *PnnYnnMnnDTnnHnnMnnS*.
+            * tz_isoformat:
+                Intended to create ISO time zone strings with default format
+                *hh:mm*.
+            * strftime:
+                A re-implementation mostly compatible with Python's *strftime*, but
+                supports only those format strings, which can also be used for dates
+                prior 1900. This method also understands how to format *datetime* and
+                *Duration* instances.
+        
+        Installation:
+        -------------
+        
+        This module can easily be installed with Python standard installation methods.
+        
+        Either use *python setup.py install* or in case you have *setuptools* or
+        *distribute* available, you can also use *easy_install*.
+        
+        Limitations:
+        ------------
+        
+           * The parser accepts several date/time representation which should be invalid
+             according to ISO 8601 standard.
+        
+             1. for date and time together, this parser accepts a mixture of basic and extended format.
+                e.g. the date could be in basic format, while the time is accepted in extended format.
+                It also allows short dates and times in date-time strings.
+             2. For incomplete dates, the first day is chosen. e.g. 19th century results in a date of
+                1901-01-01.
+             3. negative *Duration* and *timedelta* value are not fully supported yet.
+        
+        Further information:
+        --------------------
+        
+        The doc strings and unit tests should provide rather detailed information about
+        the methods and their limitations.
+        
+        The source release provides a *setup.py* script and a *buildout.cfg*. Both can
+        be used to run the unit tests included.
+        
+        Source code is available at `<http://github.com/gweis/isodate>`_.
+        
+        CHANGES
+        =======
+        
+        0.5.0 (2014-02-23)
+        ------------------
+        
+        - ISO8601Error are subclasses of ValueError now
+        - improve compatibility across various python variants and versions
+        - raise exceptions when using fractional years and months in date
+          maths with durations
+        - renamed method todatetime on Duraction objects to totimedelta
+        
+        
+        0.4.9 (2012-10-30)
+        ------------------
+        
+        - support pickling FixedOffset instances
+        - make sure parsed fractional seconds are in microseconds
+        - add leading zeros when formattig microseconds (Jarom Loveridge)
+        
+        
+        0.4.8 (2012-05-04)
+        ------------------
+        
+        - fixed incompatibility of unittests with python 2.5 and 2.6 (runs fine on 2.7
+          and 3.2)
+        
+        
+        0.4.7 (2012-01-26)
+        ------------------
+        
+        - fixed tzinfo formatting (never pass None into tzinfo.utcoffset())
+        
+        
+        0.4.6 (2012-01-06)
+        ------------------
+        
+        - added Python 3 compatibility via 2to3
+        
+        0.4.5 (2012-01-06)
+        ------------------
+        
+        - made setuptools dependency optional
+        
+        0.4.4 (2011-04-16)
+        ------------------
+        
+        - Fixed formatting of microseconds for datetime objects
+        
+        0.4.3 (2010-10-29)
+        ------------------
+        
+        - Fixed problem with %P formating and fractions (supplied by David Brooks)
+        
+        0.4.2 (2010-10-28)
+        ------------------
+        
+        - Implemented unary - for Duration (supplied by David Brooks)
+        - Output fractional seconds with '%P' format. (partly supplied by David Brooks)
+        
+        0.4.1 (2010-10-13)
+        ------------------
+        
+        - fixed bug in comparison between timedelta and Duration.
+        - fixed precision problem with microseconds (reported by Tommi Virtanen)
+        
+        0.4.0 (2009-02-09)
+        ------------------
+        
+        - added method to parse ISO 8601 time zone strings
+        - added methods to create ISO 8601 conforming strings
+        
+        0.3.0 (2009-1-05)
+        ------------------
+        
+        - Initial release
+        
+        TODOs
+        =====
+        
+        This to do list contains some thoughts and ideas about missing features, and
+        parts to think about, whether to implement them or not. This list is probably
+        not complete.
+        
+        Missing features:
+        -----------------
+        
+            * time formating does not allow to create fractional representations.
+            * parser for ISO intervals.
+            * currently microseconds are always padded to a length of 6 characters.
+              trailing 0s should be optional
+        
+        Documentation:
+        --------------
+        
+            * parse_datetime:
+               - complete documentation to show what this function allows, but ISO forbids.
+                 and vice verse.
+               - support other separators between date and time than 'T'
+        
+            * parse_date:
+               - yeardigits should be always greater than 4
+               - dates before 0001-01-01 are not supported
+        
+            * parse_duration:
+               - alternative formats are not fully supported due to parse_date restrictions
+               - standard duration format is fully supported but not very restrictive.
+        
+            * Duration:
+               - support fractional years and month in calculations
+               - implement w3c order relation? (`<http://www.w3.org/TR/xmlschema-2/#duration-order>`_)
+               - refactor to have duration mathematics only at one place.
+               - localize __str__ method (does timedelta do this?)
+               - when is a Duration negative?
+               - normalize Durations. months [00-12] and years ]-inf,+inf[
+        
+Platform: UNKNOWN
+Classifier: Development Status :: 4 - Beta
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3.2
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: Implementation :: PyPy
+Classifier: Topic :: Internet
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
diff --git a/src/isodate.egg-info/SOURCES.txt b/src/isodate.egg-info/SOURCES.txt
new file mode 100644
index 0000000..37d9c1f
--- /dev/null
+++ b/src/isodate.egg-info/SOURCES.txt
@@ -0,0 +1,26 @@
+CHANGES.txt
+MANIFEST.in
+README.rst
+TODO.txt
+setup.py
+src/isodate/__init__.py
+src/isodate/duration.py
+src/isodate/isodates.py
+src/isodate/isodatetime.py
+src/isodate/isoduration.py
+src/isodate/isoerror.py
+src/isodate/isostrf.py
+src/isodate/isotime.py
+src/isodate/isotzinfo.py
+src/isodate/tzinfo.py
+src/isodate.egg-info/PKG-INFO
+src/isodate.egg-info/SOURCES.txt
+src/isodate.egg-info/dependency_links.txt
+src/isodate.egg-info/top_level.txt
+src/isodate/tests/__init__.py
+src/isodate/tests/test_date.py
+src/isodate/tests/test_datetime.py
+src/isodate/tests/test_duration.py
+src/isodate/tests/test_pickle.py
+src/isodate/tests/test_strf.py
+src/isodate/tests/test_time.py
\ No newline at end of file
diff --git a/src/isodate.egg-info/dependency_links.txt b/src/isodate.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/src/isodate.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/src/isodate.egg-info/top_level.txt b/src/isodate.egg-info/top_level.txt
new file mode 100644
index 0000000..817963d
--- /dev/null
+++ b/src/isodate.egg-info/top_level.txt
@@ -0,0 +1 @@
+isodate
diff --git a/src/isodate/duration.py b/src/isodate/duration.py
index fa501cd..4484919 100644
--- a/src/isodate/duration.py
+++ b/src/isodate/duration.py
@@ -31,13 +31,22 @@ The class Duration allows to define durations in years and months and can be
 used as limited replacement for timedelta objects.
 '''
 from datetime import date, datetime, timedelta
+from decimal import Decimal, ROUND_FLOOR
 
 
 def fquotmod(val, low, high):
     '''
     A divmod function with boundaries.
+
     '''
-    div, mod = divmod(val - low, high - low)
+    # assumes that all the maths is done with Decimals.
+    # divmod for Decimal uses truncate instead of floor as builtin divmod, so we have
+    # to do it manually here.
+    a, b = val - low, high - low
+    div = (a / b).to_integral(ROUND_FLOOR)
+    mod = a - div * b
+    # if we were not usig Decimal, it would look like this.
+    #div, mod = divmod(val - low, high - low)
     mod += low
     return int(div), mod
 
@@ -83,6 +92,10 @@ class Duration(object):
         '''
         Initialise this Duration instance with the given parameters.
         '''
+        if not isinstance(months, Decimal):
+            months = Decimal(str(months))
+        if not isinstance(years, Decimal):
+            years = Decimal(str(years))
         self.months = months
         self.years = years
         self.tdelta = timedelta(days, seconds, microseconds, milliseconds,
@@ -140,6 +153,8 @@ class Duration(object):
             newduration.tdelta = self.tdelta + other.tdelta
             return newduration
         if isinstance(other, (date, datetime)):
+            if (not( float(self.years).is_integer() and float(self.months).is_integer())):
+                raise ValueError('fractional years or months not supported for date calculations')
             newmonth = other.month + self.months
             carry, newmonth = fquotmod(newmonth, 1, 13)
             newyear = other.year + self.years + carry
@@ -162,6 +177,8 @@ class Duration(object):
             newduration.tdelta = self.tdelta + other
             return newduration
         if isinstance(other, (date, datetime)):
+            if (not( float(self.years).is_integer() and float(self.months).is_integer())):
+                raise ValueError('fractional years or months not supported for date calculations')
             newmonth = other.month + self.months
             carry, newmonth = fquotmod(newmonth, 1, 13)
             newyear = other.year + self.years + carry
@@ -199,6 +216,8 @@ class Duration(object):
         '''
         #print '__rsub__:', self, other
         if isinstance(other, (date, datetime)):
+            if (not( float(self.years).is_integer() and float(self.months).is_integer())):
+                raise ValueError('fractional years or months not supported for date calculations')
             newmonth = other.month - self.months
             carry, newmonth = fquotmod(newmonth, 1, 13)
             newyear = other.year - self.years + carry
@@ -245,7 +264,7 @@ class Duration(object):
             return True
         return False
 
-    def todatetime(self, start=None, end=None):
+    def totimedelta(self, start=None, end=None):
         '''
         Convert this duration into a timedelta object.
 
diff --git a/src/isodate/isoduration.py b/src/isodate/isoduration.py
index 3554b1f..97affdc 100644
--- a/src/isodate/isoduration.py
+++ b/src/isodate/isoduration.py
@@ -31,6 +31,7 @@ It also provides a wrapper to strftime. This wrapper makes it easier to
 format timedelta or Duration instances as ISO conforming strings.
 '''
 from datetime import timedelta
+from decimal import Decimal
 import re
 
 from isodate.duration import Duration
@@ -103,7 +104,11 @@ def parse_duration(datestring):
             if val is None:
                 groups[key] = "0n"
             #print groups[key]
-            groups[key] = float(groups[key][:-1].replace(',', '.'))
+            if key in ('years', 'months'):
+                groups[key] = Decimal(groups[key][:-1].replace(',', '.'))
+            else:
+                # these values are passed into a timedelta object, which works with floats.
+                groups[key] = float(groups[key][:-1].replace(',', '.'))
     if groups["years"] == 0 and groups["months"] == 0:
         ret = timedelta(days=groups["days"], hours=groups["hours"],
                         minutes=groups["minutes"], seconds=groups["seconds"],
diff --git a/src/isodate/isoerror.py b/src/isodate/isoerror.py
index b690bfe..edbc5aa 100644
--- a/src/isodate/isoerror.py
+++ b/src/isodate/isoerror.py
@@ -28,5 +28,5 @@
 This module defines all exception classes in the whole package.
 '''
 
-class ISO8601Error(Exception):
+class ISO8601Error(ValueError):
     '''Raised when the given ISO string can not be parsed.'''
diff --git a/src/isodate/isostrf.py b/src/isodate/isostrf.py
index e492a39..5f3169f 100644
--- a/src/isodate/isostrf.py
+++ b/src/isodate/isostrf.py
@@ -83,7 +83,7 @@ D_ALT_EXT_ORD = 'P' + DATE_EXT_ORD_COMPLETE + 'T' + TIME_EXT_COMPLETE
 D_ALT_BAS_ORD = 'P' + DATE_BAS_ORD_COMPLETE + 'T' + TIME_BAS_COMPLETE
 
 STRF_DT_MAP = {'%d': lambda tdt, yds: '%02d' % tdt.day,
-               '%f': lambda tdt, yds: '%d' % tdt.microsecond,
+               '%f': lambda tdt, yds: '%06d' % tdt.microsecond,
                '%H': lambda tdt, yds: '%02d' % tdt.hour,
                '%j': lambda tdt, yds: '%03d' % (tdt.toordinal() -
                                             date(tdt.year, 1, 1).toordinal() +
@@ -97,13 +97,13 @@ STRF_DT_MAP = {'%d': lambda tdt, yds: '%02d' % tdt.day,
                                    (('%%0%dd' % yds) % tdt.year),
                '%C': lambda tdt, yds: (((yds != 4) and '+') or '') +\
                                    (('%%0%dd' % (yds - 2)) % (tdt.year / 100)),
-               '%h': lambda tdt, yds: tz_isoformat(tdt.tzinfo, '%h'),
-               '%Z': lambda tdt, yds: tz_isoformat(tdt.tzinfo, '%Z'),
-               '%z': lambda tdt, yds: tz_isoformat(tdt.tzinfo, '%z'),
+               '%h': lambda tdt, yds: tz_isoformat(tdt, '%h'),
+               '%Z': lambda tdt, yds: tz_isoformat(tdt, '%Z'),
+               '%z': lambda tdt, yds: tz_isoformat(tdt, '%z'),
                '%%': lambda tdt, yds: '%'}
 
 STRF_D_MAP = {'%d': lambda tdt, yds: '%02d' % tdt.days,
-              '%f': lambda tdt, yds: '%d' % tdt.microseconds,
+              '%f': lambda tdt, yds: '%06d' % tdt.microseconds,
               '%H': lambda tdt, yds: '%02d' % (tdt.seconds / 60 / 60),
               '%m': lambda tdt, yds: '%02d' % tdt.months,
               '%M': lambda tdt, yds: '%02d' % ((tdt.seconds / 60) % 60),
diff --git a/src/isodate/isotime.py b/src/isodate/isotime.py
index f0003d6..7ded2d4 100644
--- a/src/isodate/isotime.py
+++ b/src/isodate/isotime.py
@@ -123,18 +123,19 @@ def parse_time(timestring):
                                   int(groups['tzhour'] or 0),
                                   int(groups['tzmin'] or 0))
             if 'second' in groups:
-                second = Decimal(groups['second'])
+                # round to microseconds if fractional seconds are more precise
+                second = Decimal(groups['second']).quantize(Decimal('.000001'))
                 microsecond = (second - int(second)) * long(1e6)
                 # int(...) ... no rounding
                 # to_integral() ... rounding
                 return time(int(groups['hour']), int(groups['minute']),
-                            int(second), microsecond.to_integral(), tzinfo)
+                            int(second), int(microsecond.to_integral()), tzinfo)
             if 'minute' in groups:
                 minute = Decimal(groups['minute'])
                 second = (minute - int(minute)) * 60
                 microsecond = (second - int(second)) * long(1e6)
                 return time(int(groups['hour']), int(minute), int(second),
-                            microsecond.to_integral(), tzinfo)
+                            int(microsecond.to_integral()), tzinfo)
             else:
                 microsecond, second, minute = 0, 0, 0
             hour = Decimal(groups['hour'])
@@ -142,7 +143,7 @@ def parse_time(timestring):
             second = (minute - int(minute)) * 60
             microsecond = (second - int(second)) * long(1e6)
             return time(int(hour), int(minute), int(second),
-                        microsecond.to_integral(), tzinfo)
+                        int(microsecond.to_integral()), tzinfo)
     raise ISO8601Error('Unrecognised ISO 8601 time format: %r' % timestring)
 
 
diff --git a/src/isodate/isotzinfo.py b/src/isodate/isotzinfo.py
index 79797fa..97dbe8c 100644
--- a/src/isodate/isotzinfo.py
+++ b/src/isodate/isotzinfo.py
@@ -74,7 +74,7 @@ def parse_tzinfo(tzstring):
                             int(groups['tzmin'] or 0))
     raise ISO8601Error('%s not a valid time zone info' % tzstring)
 
-def tz_isoformat(tzinfo, format='%Z'):
+def tz_isoformat(dt, format='%Z'):
     '''
     return time zone offset ISO 8601 formatted. 
     The various ISO formats can be chosen with the format parameter.
@@ -87,11 +87,12 @@ def tz_isoformat(tzinfo, format='%Z'):
         %z ... +-HHMM
         %Z ... +-HH:MM
     '''
-    if (tzinfo is None) or (tzinfo.utcoffset(None) is None):
+    tzinfo = dt.tzinfo
+    if (tzinfo is None) or (tzinfo.utcoffset(dt) is None):
         return ''
-    if tzinfo.utcoffset(None) == ZERO and tzinfo.dst(None) == ZERO:
+    if tzinfo.utcoffset(dt) == ZERO and tzinfo.dst(dt) == ZERO:
         return 'Z'
-    tdelta = tzinfo.utcoffset(None)
+    tdelta = tzinfo.utcoffset(dt)
     seconds = tdelta.days * 24 * 60 * 60 + tdelta.seconds
     sign = ((seconds < 0) and '-') or '+'
     seconds = abs(seconds)
@@ -105,4 +106,4 @@ def tz_isoformat(tzinfo, format='%Z'):
         return '%s%02d%02d' % (sign, hours, minutes)
     elif format == '%h':
         return '%s%02d' % (sign, hours)
-    raise AttributeError('unknown format string "%s"' % format)
+    raise ValueError('unknown format string "%s"' % format)
diff --git a/src/isodate/tests/__init__.py b/src/isodate/tests/__init__.py
index 67512d0..bc1867d 100644
--- a/src/isodate/tests/__init__.py
+++ b/src/isodate/tests/__init__.py
@@ -14,11 +14,11 @@
 #    may be used to endorse or promote products derived from this software
 #    without specific prior written permission.
 #
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
@@ -29,7 +29,8 @@ Collect all test suites into one TestSuite instance.
 '''
 
 import unittest
-from isodate.tests import test_date, test_time, test_datetime, test_duration
+from isodate.tests import (test_date, test_time, test_datetime, test_duration,
+                           test_strf, test_pickle)
 
 def test_suite():
     '''
@@ -39,7 +40,10 @@ def test_suite():
         test_date.test_suite(),
         test_time.test_suite(),
         test_datetime.test_suite(),
-        test_duration.test_suite()])
+        test_duration.test_suite(),
+        test_strf.test_suite(),
+        test_pickle.test_suite(),
+        ])
 
 if __name__ == '__main__':
     unittest.main(defaultTest='test_suite')
diff --git a/src/isodate/tests/test_date.py b/src/isodate/tests/test_date.py
index fb6ba8c..3a1b4a6 100644
--- a/src/isodate/tests/test_date.py
+++ b/src/isodate/tests/test_date.py
@@ -118,5 +118,9 @@ def test_suite():
                                           expectation, format))
     return suite
 
+# load_tests Protocol
+def load_tests(loader, tests, pattern):
+    return test_suite()
+    
 if __name__ == '__main__':
     unittest.main(defaultTest='test_suite')
diff --git a/src/isodate/tests/test_datetime.py b/src/isodate/tests/test_datetime.py
index fd50039..f6aaa51 100644
--- a/src/isodate/tests/test_datetime.py
+++ b/src/isodate/tests/test_datetime.py
@@ -32,7 +32,7 @@ from datetime import datetime
 
 from isodate import parse_datetime, UTC, FixedOffset, datetime_isoformat
 from isodate import DATE_BAS_COMPLETE, TIME_BAS_MINUTE, TIME_BAS_COMPLETE
-from isodate import DATE_EXT_COMPLETE, TIME_EXT_MINUTE
+from isodate import DATE_EXT_COMPLETE, TIME_EXT_MINUTE, TIME_EXT_COMPLETE
 from isodate import TZ_BAS, TZ_EXT, TZ_HOUR
 from isodate import DATE_BAS_ORD_COMPLETE, DATE_EXT_ORD_COMPLETE
 from isodate import DATE_BAS_WEEK_COMPLETE, DATE_EXT_WEEK_COMPLETE
@@ -41,27 +41,51 @@ from isodate import DATE_BAS_WEEK_COMPLETE, DATE_EXT_WEEK_COMPLETE
 # result from the parse_datetime method. A result of None means an ISO8601Error
 # is expected.
 TEST_CASES = [('19850412T1015', datetime(1985, 4, 12, 10, 15),
-               DATE_BAS_COMPLETE + 'T' + TIME_BAS_MINUTE),
+               DATE_BAS_COMPLETE + 'T' + TIME_BAS_MINUTE,
+               '19850412T1015'),
               ('1985-04-12T10:15', datetime(1985, 4, 12, 10, 15),
-               DATE_EXT_COMPLETE + 'T' + TIME_EXT_MINUTE),
+               DATE_EXT_COMPLETE + 'T' + TIME_EXT_MINUTE,
+               '1985-04-12T10:15'),
               ('1985102T1015Z', datetime(1985, 4, 12, 10, 15, tzinfo=UTC),
-               DATE_BAS_ORD_COMPLETE + 'T' + TIME_BAS_MINUTE + TZ_BAS),
+               DATE_BAS_ORD_COMPLETE + 'T' + TIME_BAS_MINUTE + TZ_BAS,
+               '1985102T1015Z'),
               ('1985-102T10:15Z', datetime(1985, 4, 12, 10, 15, tzinfo=UTC),
-               DATE_EXT_ORD_COMPLETE + 'T' + TIME_EXT_MINUTE + TZ_EXT),
+               DATE_EXT_ORD_COMPLETE + 'T' + TIME_EXT_MINUTE + TZ_EXT,
+               '1985-102T10:15Z'),
               ('1985W155T1015+0400', datetime(1985, 4, 12, 10, 15,
                                               tzinfo=FixedOffset(4, 0,
                                                                  '+0400')),
-               DATE_BAS_WEEK_COMPLETE + 'T' + TIME_BAS_MINUTE + TZ_BAS),
+               DATE_BAS_WEEK_COMPLETE + 'T' + TIME_BAS_MINUTE + TZ_BAS,
+               '1985W155T1015+0400'),
               ('1985-W15-5T10:15+04', datetime(1985, 4, 12, 10, 15,
                                                tzinfo=FixedOffset(4, 0,
-                                                                  '+0400')),
-               DATE_EXT_WEEK_COMPLETE + 'T' + TIME_EXT_MINUTE + TZ_HOUR),
+                                                                  '+0400'),),
+               DATE_EXT_WEEK_COMPLETE + 'T' + TIME_EXT_MINUTE + TZ_HOUR,
+               '1985-W15-5T10:15+04'),
               ('20110410T101225.123000Z',
                datetime(2011, 4, 10, 10, 12, 25, 123000, tzinfo=UTC),
-               DATE_BAS_COMPLETE + 'T' + TIME_BAS_COMPLETE + ".%f" + TZ_BAS)]
+               DATE_BAS_COMPLETE + 'T' + TIME_BAS_COMPLETE + ".%f" + TZ_BAS,
+               '20110410T101225.123000Z'),
+              ('2012-10-12T08:29:46.069178Z',
+               datetime(2012, 10, 12, 8, 29, 46, 69178, tzinfo=UTC),
+               DATE_EXT_COMPLETE + 'T' + TIME_EXT_COMPLETE + '.%f' + TZ_BAS,
+               '2012-10-12T08:29:46.069178Z'),
+              ('2012-10-12T08:29:46.691780Z',
+               datetime(2012, 10, 12, 8, 29, 46, 691780, tzinfo=UTC),
+               DATE_EXT_COMPLETE + 'T' + TIME_EXT_COMPLETE + '.%f' + TZ_BAS,
+               '2012-10-12T08:29:46.691780Z'),
+              ('2012-10-30T08:55:22.1234567Z',
+               datetime(2012, 10, 30, 8, 55, 22, 123457, tzinfo=UTC),
+               DATE_EXT_COMPLETE + 'T' + TIME_EXT_COMPLETE + '.%f' + TZ_BAS,
+               '2012-10-30T08:55:22.123457Z'),
+              ('2012-10-30T08:55:22.1234561Z',
+               datetime(2012, 10, 30, 8, 55, 22, 123456, tzinfo=UTC),
+               DATE_EXT_COMPLETE + 'T' + TIME_EXT_COMPLETE + '.%f' + TZ_BAS,
+               '2012-10-30T08:55:22.123456Z')
+               ]
 
 
-def create_testcase(datetimestring, expectation, format):
+def create_testcase(datetimestring, expectation, format, output):
     """
     Create a TestCase class for a specific test.
 
@@ -92,7 +116,7 @@ def create_testcase(datetimestring, expectation, format):
                                   datetime_isoformat, expectation, format)
             else:
                 self.assertEqual(datetime_isoformat(expectation, format),
-                                 datetimestring)
+                                 output)
 
     return unittest.TestLoader().loadTestsFromTestCase(TestDateTime)
 
@@ -102,9 +126,13 @@ def test_suite():
     Construct a TestSuite instance for all test cases.
     '''
     suite = unittest.TestSuite()
-    for datetimestring, expectation, format in TEST_CASES:
-        suite.addTest(create_testcase(datetimestring, expectation, format))
+    for datetimestring, expectation, format, output in TEST_CASES:
+        suite.addTest(create_testcase(datetimestring, expectation, format, output))
     return suite
 
+# load_tests Protocol
+def load_tests(loader, tests, pattern):
+    return test_suite()
+    
 if __name__ == '__main__':
     unittest.main(defaultTest='test_suite')
diff --git a/src/isodate/tests/test_duration.py b/src/isodate/tests/test_duration.py
index d8b4cf2..e69ae17 100644
--- a/src/isodate/tests/test_duration.py
+++ b/src/isodate/tests/test_duration.py
@@ -192,25 +192,43 @@ DATE_CALC_TEST_CASES = (
                     (Duration(years=1, months=1, weeks=5),
                      date(2000, 1, 30),
                      date(2001, 4, 4)),
-                    (Duration(years=1, months=1, weeks=5),
-                     'raise exception',
-                     None),
-                    ('raise exception',
-                     Duration(years=1, months=1, weeks=5),
+                    (parse_duration("P1Y1M5W"),
+                     date(2000, 1, 30),
+                     date(2001, 4, 4)),
+                    (parse_duration("P0.5Y"),
+                     date(2000, 1, 30),
                      None),
+                    (Duration(years=1, months=1, hours=3),
+                     datetime(2000, 1, 30, 12, 15, 00),
+                     datetime(2001, 2, 28, 15, 15, 00)),
+                    (parse_duration("P1Y1MT3H"),
+                     datetime(2000, 1, 30, 12, 15, 00),
+                     datetime(2001, 2, 28, 15, 15, 00)),
                     (Duration(years=1, months=2),
                      timedelta(days=1),
                      Duration(years=1, months=2, days=1)),
                     (timedelta(days=1),
                      Duration(years=1, months=2),
                      Duration(years=1, months=2, days=1)),
-                    #(date(2000, 1, 1),
-                    # Duration(years=1.5),
-                    # date(2001, 6, 1)),
-                    #(date(2000, 1, 1),
-                    # Duration(years=1, months=1.5),
-                    # date(2001, 2, 14)),
-                     )
+                    (datetime(2008, 1, 1, 0, 2),
+                     Duration(months=1),
+                     datetime(2008, 2, 1, 0, 2)),
+                    (datetime.strptime("200802", "%Y%M"),
+                     parse_duration("P1M"),
+                     datetime(2008, 2, 1, 0, 2)),
+                    (datetime(2008, 2, 1),
+                     Duration(months=1),
+                     datetime(2008, 3, 1)),
+                    (datetime.strptime("200802", "%Y%m"),
+                     parse_duration("P1M"),
+                     datetime(2008, 3, 1)),
+                    # (date(2000, 1, 1),
+                    #  Duration(years=1.5),
+                    #  date(2001, 6, 1)),
+                    # (date(2000, 1, 1),
+                    #  Duration(years=1, months=1.5),
+                    #  date(2001, 2, 14)),
+                    )
 
 
 class DurationTest(unittest.TestCase):
@@ -239,6 +257,11 @@ class DurationTest(unittest.TestCase):
                           date(2000, 1, 1))
         self.assertRaises(TypeError, operator.sub, 'raise exc',
                           Duration(years=1))
+        self.assertRaises(TypeError, operator.add,
+                          Duration(years=1, months=1, weeks=5),
+                          'raise exception')
+        self.assertRaises(TypeError, operator.add, 'raise exception',
+                          Duration(years=1, months=1, weeks=5))
 
     def test_parseerror(self):
         '''
@@ -289,7 +312,6 @@ class DurationTest(unittest.TestCase):
         self.assertEqual(duration_isoformat(dur), 'P3Y7M23DT5H25M0.33S')
         self.assertEqual(duration_isoformat(-dur), '-P3Y7M23DT5H25M0.33S')
 
-
     def test_equal(self):
         '''
         Test __eq__ and __ne__ methods.
@@ -313,6 +335,20 @@ class DurationTest(unittest.TestCase):
         #        treats a != b the same b != a
         #self.assertNotEqual(timedelta(days=1), Duration(days=1))
 
+    def test_totimedelta(self):
+        '''
+        Test conversion form Duration to timedelta.
+        '''
+        dur = Duration(years=1, months=2, days=10)
+        self.assertEqual(dur.totimedelta(datetime(1998, 2, 25)), timedelta(434))
+        # leap year has one day more in february
+        self.assertEqual(dur.totimedelta(datetime(2000, 2, 25)), timedelta(435))
+        dur = Duration(months=2)
+        # march is longer than february, but april is shorter than march (cause only one day difference compared to 2)
+        self.assertEqual(dur.totimedelta(datetime(2000, 2, 25)), timedelta(60))
+        self.assertEqual(dur.totimedelta(datetime(2001, 2, 25)), timedelta(59))
+        self.assertEqual(dur.totimedelta(datetime(2001, 3, 25)), timedelta(61))
+
 
 def create_parsetestcase(durationstring, expectation, format, altstr):
     """
@@ -451,7 +487,7 @@ def create_datecalctestcase(start, duration, expectation):
             Test operator +.
             '''
             if expectation is None:
-                self.assertRaises(TypeError, operator.add, start, duration)
+                self.assertRaises(ValueError, operator.add, start, duration)
             else:
                 self.assertEqual(start + duration, expectation)
 
@@ -475,5 +511,9 @@ def test_suite():
     suite.addTest(unittest.TestLoader().loadTestsFromTestCase(DurationTest))
     return suite
 
+# load_tests Protocol
+def load_tests(loader, tests, pattern):
+    return test_suite()
+
 if __name__ == '__main__':
     unittest.main(defaultTest='test_suite')
diff --git a/src/isodate/tests/test_pickle.py b/src/isodate/tests/test_pickle.py
new file mode 100644
index 0000000..952c238
--- /dev/null
+++ b/src/isodate/tests/test_pickle.py
@@ -0,0 +1,35 @@
+import unittest
+import cPickle as pickle
+import isodate
+
+
+class TestPickle(unittest.TestCase):
+    '''
+    A test case template to parse an ISO datetime string into a
+    datetime object.
+    '''
+
+    def test_pickle(self):
+        '''
+        Parse an ISO datetime string and compare it to the expected value.
+        '''
+        dti = isodate.parse_datetime('2012-10-26T09:33+00:00')
+        pikl = pickle.dumps(dti, 2)
+        dto = pickle.loads(pikl)
+        self.assertEqual(dti, dto)
+
+
+def test_suite():
+    '''
+    Construct a TestSuite instance for all test cases.
+    '''
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.TestLoader().loadTestsFromTestCase(TestPickle))
+    return suite
+
+# load_tests Protocol
+def load_tests(loader, tests, pattern):
+    return test_suite()
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')
diff --git a/src/isodate/tests/test_strf.py b/src/isodate/tests/test_strf.py
new file mode 100644
index 0000000..c7f1c55
--- /dev/null
+++ b/src/isodate/tests/test_strf.py
@@ -0,0 +1,130 @@
+##############################################################################
+# Copyright 2009, Gerhard Weis
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+#  * Redistributions of source code must retain the above copyright notice,
+#    this list of conditions and the following disclaimer.
+#  * Redistributions in binary form must reproduce the above copyright notice,
+#    this list of conditions and the following disclaimer in the documentation
+#    and/or other materials provided with the distribution.
+#  * Neither the name of the authors nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT
+##############################################################################
+'''
+Test cases for the isodate module.
+'''
+import unittest
+import time
+from datetime import datetime, timedelta
+from isodate import strftime
+from isodate import LOCAL
+from isodate import DT_EXT_COMPLETE
+from isodate import tzinfo
+
+
+TEST_CASES = ((datetime(2012, 12, 25, 13, 30, 0, 0, LOCAL), DT_EXT_COMPLETE,
+               "2012-12-25T13:30:00+10:00"),
+              # DST ON
+              (datetime(1999, 12, 25, 13, 30, 0, 0, LOCAL), DT_EXT_COMPLETE,
+               "1999-12-25T13:30:00+11:00"),
+              # microseconds
+              (datetime(2012, 10, 12, 8, 29, 46, 69178), "%Y-%m-%dT%H:%M:%S.%f",
+               "2012-10-12T08:29:46.069178"),
+              (datetime(2012, 10, 12, 8, 29, 46, 691780), "%Y-%m-%dT%H:%M:%S.%f",
+               "2012-10-12T08:29:46.691780"),
+              )
+
+
+def create_testcase(dt, format, expectation):
+    """
+    Create a TestCase class for a specific test.
+
+    This allows having a separate TestCase for each test tuple from the
+    TEST_CASES list, so that a failed test won't stop other tests.
+    """
+
+    class TestDate(unittest.TestCase):
+        '''
+        A test case template to test ISO date formatting.
+        '''
+
+        # local time zone mock function
+        def localtime_mock(self, secs):
+            """
+            mock time.localtime so that it always returns a time_struct with tm_idst=1
+            """
+            tt = self.ORIG['localtime'](secs)
+            # befor 2000 everything is dst, after 2000 no dst.
+            if tt.tm_year < 2000:
+                dst = 1
+            else:
+                dst = 0
+            tt = (tt.tm_year, tt.tm_mon, tt.tm_mday,
+                  tt.tm_hour, tt.tm_min, tt.tm_sec,
+                  tt.tm_wday, tt.tm_yday, dst)
+            return time.struct_time(tt)
+
+        def setUp(self):
+            self.ORIG = {}
+            self.ORIG['STDOFFSET'] = tzinfo.STDOFFSET
+            self.ORIG['DSTOFFSET'] = tzinfo.DSTOFFSET
+            self.ORIG['DSTDIFF'] = tzinfo.DSTDIFF
+            self.ORIG['localtime'] = time.localtime
+            # ovveride all saved values with fixtures.
+            # calculate LOCAL TZ offset, so that this test runs in every time zone
+            tzinfo.STDOFFSET = timedelta(seconds=36000)  # assume we are in +10:00
+            tzinfo.DSTOFFSET = timedelta(seconds=39600)  # assume DST = +11:00
+            tzinfo.DSTDIFF = tzinfo.DSTOFFSET - tzinfo.STDOFFSET
+            time.localtime = self.localtime_mock
+
+        def tearDown(self):
+            # restore test fixtures
+            tzinfo.STDOFFSET = self.ORIG['STDOFFSET']
+            tzinfo.DSTOFFSET = self.ORIG['DSTOFFSET']
+            tzinfo.DSTDIFF = self.ORIG['DSTDIFF']
+            time.localtime = self.ORIG['localtime']
+
+        def test_format(self):
+            '''
+            Take date object and create ISO string from it.
+            This is the reverse test to test_parse.
+            '''
+            if expectation is None:
+                self.assertRaises(AttributeError,
+                                  strftime(dt, format))
+            else:
+                self.assertEqual(strftime(dt, format),
+                                 expectation)
+
+    return unittest.TestLoader().loadTestsFromTestCase(TestDate)
+
+
+def test_suite():
+    '''
+    Construct a TestSuite instance for all test cases.
+    '''
+    suite = unittest.TestSuite()
+    for dt, format, expectation in TEST_CASES:
+        suite.addTest(create_testcase(dt, format, expectation))
+    return suite
+
+# load_tests Protocol
+def load_tests(loader, tests, pattern):
+    return test_suite()
+    
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')
diff --git a/src/isodate/tests/test_time.py b/src/isodate/tests/test_time.py
index d71a3e2..cdce704 100644
--- a/src/isodate/tests/test_time.py
+++ b/src/isodate/tests/test_time.py
@@ -135,5 +135,9 @@ def test_suite():
         suite.addTest(create_testcase(timestring, expectation, format))
     return suite
 
+ # load_tests Protocol
+def load_tests(loader, tests, pattern):
+    return test_suite()
+
 if __name__ == '__main__':
     unittest.main(defaultTest='test_suite')
diff --git a/src/isodate/tzinfo.py b/src/isodate/tzinfo.py
index 776d905..820c88d 100644
--- a/src/isodate/tzinfo.py
+++ b/src/isodate/tzinfo.py
@@ -1,5 +1,5 @@
 '''
-This module provides some datetime.tzinfo implementations. 
+This module provides some datetime.tzinfo implementations.
 
 All those classes are taken from the Python documentation.
 '''
@@ -7,14 +7,14 @@ from datetime import timedelta, tzinfo
 import time
 
 ZERO = timedelta(0)
-# constant for zero time offset.    
+# constant for zero time offset.
 
 class Utc(tzinfo):
     '''UTC
-    
+
     Universal time coordinated time zone.
     '''
-    
+
     def utcoffset(self, dt):
         '''
         Return offset from UTC in minutes east of UTC, which is ZERO for UTC.
@@ -39,16 +39,16 @@ UTC = Utc()
 class FixedOffset(tzinfo):
     '''
     A class building tzinfo objects for fixed-offset time zones.
-    
-    Note that FixedOffset(0, "UTC") is a different way to build a
-    UTC tzinfo object.
+
+    Note that FixedOffset(0, 0, "UTC") or FixedOffset() is a different way to
+    build a UTC tzinfo object.
     '''
-    
-    def __init__(self, offset_hours, offset_minutes, name):
+
+    def __init__(self, offset_hours=0, offset_minutes=0, name="UTC"):
         '''
         Initialise an instance with time offset and name.
         The time offset should be positive for time zones east of UTC
-        and negate for time zones west of UTC. 
+        and negate for time zones west of UTC.
         '''
         self.__offset = timedelta(hours=offset_hours, minutes=offset_minutes)
         self.__name = name
@@ -68,11 +68,11 @@ class FixedOffset(tzinfo):
 
     def dst(self, dt):
         '''
-        Return the daylight saving time (DST) adjustment, in minutes east of 
+        Return the daylight saving time (DST) adjustment, in minutes east of
         UTC.
         '''
         return ZERO
-    
+
     def __repr__(self):
         '''
         Return nicely formatted repr string.
@@ -93,9 +93,9 @@ DSTDIFF = DSTOFFSET - STDOFFSET
 # difference between local time zone and local DST time zone
 
 class LocalTimezone(tzinfo):
-    '''
+    """
     A class capturing the platform's idea of local time.
-    '''
+    """
 
     def utcoffset(self, dt):
         '''

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/isodate.git



More information about the Python-modules-commits mailing list