[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