[Checkins] SVN: zc.iso8601/branches/dev/ include zc.iso8601 code to do what I need right now

Fred L. Drake, Jr. fdrake at gmail.com
Mon May 12 17:40:38 EDT 2008


Log message for revision 86668:
  include zc.iso8601 code to do what I need right now

Changed:
  _U  zc.iso8601/branches/dev/
  A   zc.iso8601/branches/dev/buildout.cfg
  A   zc.iso8601/branches/dev/setup.py
  A   zc.iso8601/branches/dev/src/
  A   zc.iso8601/branches/dev/src/zc/
  A   zc.iso8601/branches/dev/src/zc/__init__.py
  A   zc.iso8601/branches/dev/src/zc/iso8601/
  A   zc.iso8601/branches/dev/src/zc/iso8601/CHANGES.txt
  A   zc.iso8601/branches/dev/src/zc/iso8601/README.txt
  A   zc.iso8601/branches/dev/src/zc/iso8601/__init__.py
  A   zc.iso8601/branches/dev/src/zc/iso8601/parse.py
  A   zc.iso8601/branches/dev/src/zc/iso8601/tests.py

-=-

Property changes on: zc.iso8601/branches/dev
___________________________________________________________________
Name: svn:ignore
   + bin
build
develop-eggs
dist
parts
.installed.cfg


Added: zc.iso8601/branches/dev/buildout.cfg
===================================================================
--- zc.iso8601/branches/dev/buildout.cfg	                        (rev 0)
+++ zc.iso8601/branches/dev/buildout.cfg	2008-05-12 21:40:38 UTC (rev 86668)
@@ -0,0 +1,7 @@
+[buildout]
+develop = .
+parts = test
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = zc.iso8601


Property changes on: zc.iso8601/branches/dev/buildout.cfg
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:eol-style
   + native

Added: zc.iso8601/branches/dev/setup.py
===================================================================
--- zc.iso8601/branches/dev/setup.py	                        (rev 0)
+++ zc.iso8601/branches/dev/setup.py	2008-05-12 21:40:38 UTC (rev 86668)
@@ -0,0 +1,41 @@
+# Setup for zc.iso8601.
+
+import os
+import setuptools
+
+
+def read(path):
+    return open(path).read()
+
+
+def long_description():
+    here = os.path.dirname(os.path.abspath(__file__))
+    paths = [os.path.join(here, "src/zc/iso8601", fn)
+             for fn in "README.txt", "CHANGES.txt"]
+    return "\n\n".join([open(path).read() for path in paths])
+
+
+setuptools.setup(
+    name="zc.iso8601",
+    version="0.1.0dev",
+    description="ISO 8601 utility functions",
+    url="http://pypi.python.org/pypi/zc.iso8601/",
+    long_description=long_description(),
+    author="Fred Drake",
+    author_email="fdrake at gmail.com",
+    license="ZPL 2.1",
+    classifiers=[
+        "License :: OSI Approved :: Zope Public License",
+        "Programming Language :: Python",
+        ],
+    platforms="any",
+    package_dir={"": "src"},
+    packages=setuptools.find_packages("src"),
+    namespace_packages=["zc"],
+    install_requires=[
+        "pytz",
+        "setuptools",
+        "zope.testing",
+        ],
+    zip_safe=False,
+    )


Property changes on: zc.iso8601/branches/dev/setup.py
___________________________________________________________________
Name: svn:mime-type
   + text/x-python
Name: svn:eol-style
   + native

Added: zc.iso8601/branches/dev/src/zc/__init__.py
===================================================================
--- zc.iso8601/branches/dev/src/zc/__init__.py	                        (rev 0)
+++ zc.iso8601/branches/dev/src/zc/__init__.py	2008-05-12 21:40:38 UTC (rev 86668)
@@ -0,0 +1,8 @@
+# This directory is a Python namespace package.
+try:
+    import pkg_resources
+except ImportError:
+    import pkgutil
+    __path__ = pkgutil.extend_path(__path__, __name__)
+else:
+    pkg_resources.declare_namespace(__name__)


Property changes on: zc.iso8601/branches/dev/src/zc/__init__.py
___________________________________________________________________
Name: svn:mime-type
   + text/x-python
Name: svn:eol-style
   + native

Added: zc.iso8601/branches/dev/src/zc/iso8601/CHANGES.txt
===================================================================
--- zc.iso8601/branches/dev/src/zc/iso8601/CHANGES.txt	                        (rev 0)
+++ zc.iso8601/branches/dev/src/zc/iso8601/CHANGES.txt	2008-05-12 21:40:38 UTC (rev 86668)
@@ -0,0 +1,7 @@
+Changes
+-------
+
+1.0.0 (2008-05-12)
+~~~~~~~~~~~~~~~~~~
+
+Initial release.


Property changes on: zc.iso8601/branches/dev/src/zc/iso8601/CHANGES.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:eol-style
   + native

Added: zc.iso8601/branches/dev/src/zc/iso8601/README.txt
===================================================================
--- zc.iso8601/branches/dev/src/zc/iso8601/README.txt	                        (rev 0)
+++ zc.iso8601/branches/dev/src/zc/iso8601/README.txt	2008-05-12 21:40:38 UTC (rev 86668)
@@ -0,0 +1,182 @@
+==========================
+ISO 8601 utility functions
+==========================
+
+This package collects together functions supporting the data formats described
+in ISO 8601.
+
+
+Parsing date/time values with time zone information
+---------------------------------------------------
+
+There is a function that parses text and returns date/time values with time
+zone offsets:
+
+    >>> from zc.iso8601.parse import datetimetz
+
+Both the "verbose" and "short" forms of ISO 8601 times are accepted.  The
+verbose form includes hyphens in the date and colons in the time, and the
+short form omits them.  We'll start with verbose examples, and will then
+repeat all of the examples in short form.  The verbose form is generally
+preferred in practice since it is substantially more readable for humans.
+
+Times in UTC may be encoded using either the "Z" notation or "+00:00" (or
+"-00:00").  Let try a few examples:
+
+    >>> datetimetz(u"2006-12-02T23:40:42Z")
+    datetime.datetime(2006, 12, 2, 23, 40, 42, tzinfo=<UTC>)
+
+    >>> datetimetz(u"2006-12-02T23:40:42+00:00")
+    datetime.datetime(2006, 12, 2, 23, 40, 42, tzinfo=<UTC>)
+
+    >>> datetimetz(u"2006-12-02T23:40:42-00:00")
+    datetime.datetime(2006, 12, 2, 23, 40, 42, tzinfo=<UTC>)
+
+The time zone information must be given explicitly, however; it cannot be
+omitted:
+
+    >>> datetimetz(u"2006-12-02T23:40:42")
+    Traceback (most recent call last):
+    ValueError: could not parse ISO 8601 datetime: u'2006-12-02T23:40:42'
+
+Other time zones are converted to UTC:
+
+    >>> datetimetz(u"2006-12-02T23:40:42-01:00")
+    datetime.datetime(2006, 12, 3, 0, 40, 42, tzinfo=<UTC>)
+
+    >>> datetimetz(u"2006-12-02T23:40:42-04:00")
+    datetime.datetime(2006, 12, 3, 3, 40, 42, tzinfo=<UTC>)
+
+    >>> datetimetz(u"2006-12-02T23:40:42-05:00")
+    datetime.datetime(2006, 12, 3, 4, 40, 42, tzinfo=<UTC>)
+
+    >>> datetimetz(u"2006-12-02T23:40:42+01:00")
+    datetime.datetime(2006, 12, 2, 22, 40, 42, tzinfo=<UTC>)
+
+We'll even make up a few that have non-zero values for the minutes portion of
+the offset.  While these are made-up time zones, there are real time zones
+that aren't exactly some interger number of hours offset from UTC:
+
+    >>> datetimetz(u"2006-12-02T23:40:42-05:25")
+    datetime.datetime(2006, 12, 3, 5, 5, 42, tzinfo=<UTC>)
+
+    >>> datetimetz(u"2006-12-02T23:40:42+01:25")
+    datetime.datetime(2006, 12, 2, 22, 15, 42, tzinfo=<UTC>)
+
+The seconds field, as shown above, is optional.  If omitted, the seconds field
+of the time will be zero:
+
+    >>> datetimetz(u"2006-12-02T23:40Z")
+    datetime.datetime(2006, 12, 2, 23, 40, tzinfo=<UTC>)
+
+    >>> datetimetz(u"2006-12-02T23:40-05:00")
+    datetime.datetime(2006, 12, 3, 4, 40, tzinfo=<UTC>)
+
+When the seconds are specified, fractional seconds are supported:
+
+    >>> datetimetz(u"2008-05-12T14:30:32.000Z")
+    datetime.datetime(2008, 5, 12, 14, 30, 32, tzinfo=<UTC>)
+
+    >>> datetimetz(u"2008-05-12T14:30:32.5Z")
+    datetime.datetime(2008, 5, 12, 14, 30, 32, 500000, tzinfo=<UTC>)
+
+    >>> datetimetz(u"2008-05-12T14:30:32.01Z")
+    datetime.datetime(2008, 5, 12, 14, 30, 32, 10000, tzinfo=<UTC>)
+
+    >>> datetimetz(u"2008-05-12T14:30:32.000001+00:00")
+    datetime.datetime(2008, 5, 12, 14, 30, 32, 1, tzinfo=<UTC>)
+
+Fractional seconds smaller than 1 microsecond are simply thrown away:
+
+    >>> datetimetz(u"2008-05-12T14:30:32.00000099999+00:00")
+    datetime.datetime(2008, 5, 12, 14, 30, 32, tzinfo=<UTC>)
+
+If a space is used instead of the "T" separator, the input is still
+interpreted properly:
+
+    >>> datetimetz(u"2006-12-02 23:40:42Z")
+    datetime.datetime(2006, 12, 2, 23, 40, 42, tzinfo=<UTC>)
+
+    >>> datetimetz(u"2008-05-12 14:30:32.01Z")
+    datetime.datetime(2008, 5, 12, 14, 30, 32, 10000, tzinfo=<UTC>)
+
+Surrounding whitespace is ignored, and multiple whitespace characters between
+the date and time fields is collapsed and treated as if the extra whitespace
+characters were not present:
+
+    >>> datetimetz(u"""
+    ...   2006-12-02
+    ...   \t\r\f
+    ...   23:40:42Z
+    ... """)
+    datetime.datetime(2006, 12, 2, 23, 40, 42, tzinfo=<UTC>)
+
+    >>> datetimetz(u"""
+    ...   2008-05-12
+    ...   \t\r\f
+    ...   14:30:32.01Z
+    ... """)
+    datetime.datetime(2008, 5, 12, 14, 30, 32, 10000, tzinfo=<UTC>)
+
+Other whitespace is considered an error:
+
+    >>> datetimetz(u"  2006 -12-02  23:40:42Z  ")
+    Traceback (most recent call last):
+    ValueError: could not parse ISO 8601 datetime: u'2006 -12-02 23:40:42Z'
+
+Now, let's look at how the same examples do in the short form.  Note that time
+zone offsets given in numeric form continue to include the minus sign; that
+carries necessary information, while the hyphens in the date are purely for
+human consumption:
+
+    >>> datetimetz(u"20061202T234042Z")
+    datetime.datetime(2006, 12, 2, 23, 40, 42, tzinfo=<UTC>)
+
+    >>> datetimetz(u"20061202T234042+0000")
+    datetime.datetime(2006, 12, 2, 23, 40, 42, tzinfo=<UTC>)
+
+    >>> datetimetz(u"20061202T234042-0000")
+    datetime.datetime(2006, 12, 2, 23, 40, 42, tzinfo=<UTC>)
+
+    >>> datetimetz(u"20061202T234042")
+    Traceback (most recent call last):
+    ValueError: could not parse ISO 8601 datetime: u'20061202T234042'
+
+    >>> datetimetz(u"20061202T234042-0100")
+    datetime.datetime(2006, 12, 3, 0, 40, 42, tzinfo=<UTC>)
+
+    >>> datetimetz(u"20061202T234042-0400")
+    datetime.datetime(2006, 12, 3, 3, 40, 42, tzinfo=<UTC>)
+
+    >>> datetimetz(u"20061202T234042-0500")
+    datetime.datetime(2006, 12, 3, 4, 40, 42, tzinfo=<UTC>)
+
+    >>> datetimetz(u"20061202T234042+0100")
+    datetime.datetime(2006, 12, 2, 22, 40, 42, tzinfo=<UTC>)
+
+    >>> datetimetz(u"20061202T234042-0525")
+    datetime.datetime(2006, 12, 3, 5, 5, 42, tzinfo=<UTC>)
+
+    >>> datetimetz(u"20061202T234042+0125")
+    datetime.datetime(2006, 12, 2, 22, 15, 42, tzinfo=<UTC>)
+
+    >>> datetimetz(u"20061202T2340Z")
+    datetime.datetime(2006, 12, 2, 23, 40, tzinfo=<UTC>)
+
+    >>> datetimetz(u"20061202T2340-0500")
+    datetime.datetime(2006, 12, 3, 4, 40, tzinfo=<UTC>)
+
+    >>> datetimetz(u"20080512T143032.000Z")
+    datetime.datetime(2008, 5, 12, 14, 30, 32, tzinfo=<UTC>)
+
+    >>> datetimetz(u"20080512T143032.5Z")
+    datetime.datetime(2008, 5, 12, 14, 30, 32, 500000, tzinfo=<UTC>)
+
+    >>> datetimetz(u"20080512T143032.01Z")
+    datetime.datetime(2008, 5, 12, 14, 30, 32, 10000, tzinfo=<UTC>)
+
+    >>> datetimetz(u"20080512T143032.000001+0000")
+    datetime.datetime(2008, 5, 12, 14, 30, 32, 1, tzinfo=<UTC>)
+
+    >>> datetimetz(u"20080512T143032.00000099999+00:00")
+    datetime.datetime(2008, 5, 12, 14, 30, 32, tzinfo=<UTC>)


Property changes on: zc.iso8601/branches/dev/src/zc/iso8601/README.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:eol-style
   + native

Added: zc.iso8601/branches/dev/src/zc/iso8601/__init__.py
===================================================================
--- zc.iso8601/branches/dev/src/zc/iso8601/__init__.py	                        (rev 0)
+++ zc.iso8601/branches/dev/src/zc/iso8601/__init__.py	2008-05-12 21:40:38 UTC (rev 86668)
@@ -0,0 +1 @@
+# This directory is a Python package.


Property changes on: zc.iso8601/branches/dev/src/zc/iso8601/__init__.py
___________________________________________________________________
Name: svn:mime-type
   + text/x-python
Name: svn:eol-style
   + native

Added: zc.iso8601/branches/dev/src/zc/iso8601/parse.py
===================================================================
--- zc.iso8601/branches/dev/src/zc/iso8601/parse.py	                        (rev 0)
+++ zc.iso8601/branches/dev/src/zc/iso8601/parse.py	2008-05-12 21:40:38 UTC (rev 86668)
@@ -0,0 +1,99 @@
+##############################################################################
+#
+# Copyright (c) 2006-2008 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.
+#
+##############################################################################
+"""\
+Utility functions for parsing ISO 8601 values.
+
+"""
+__docformat__ = "reStructuredText"
+
+import datetime
+import pytz
+import re
+
+
+_tz_re = "(?:Z|(?P<tzdir>[-+])(?P<tzhour>\d\d):(?P<tzmin>\d\d))"
+
+# "Verbose" ISO 8601, with hyphens and colons:
+_datetime_re1 = """\
+    (?P<year>\d\d\d\d)
+    -(?P<month>\d\d)
+    -(?P<day>\d\d)
+    [T\ ]
+    (?P<hour>\d\d)
+    :(?P<minute>\d\d)
+    (?::(?P<second>\d\d(?:\.\d+)?))?
+    """ + _tz_re
+
+# "Compact" ISO 8601, without hyphens and colons:
+_datetime_re2 = """\
+    (?P<year>\d\d\d\d)
+    (?P<month>\d\d)
+    (?P<day>\d\d)
+    [T\ ]
+    (?P<hour>\d\d)
+    (?P<minute>\d\d)
+    (?P<second>\d\d(?:\.\d+)?)?
+    """ + _tz_re.replace("):(", "):?(")
+
+_datetime_rx1 = re.compile(_datetime_re1, re.IGNORECASE | re.VERBOSE)
+_datetime_rx2 = re.compile(_datetime_re2, re.IGNORECASE | re.VERBOSE)
+
+
+def datetimetz(string):
+    """Parse an ISO 8601 date including timezone information.
+
+    Returns a Python datetime object.
+
+    """
+    string = " ".join(string.split())
+    m = _datetime_rx1.match(string)
+    if m is None:
+        m = _datetime_rx2.match(string)
+        if m is None:
+            raise ValueError("could not parse ISO 8601 datetime: %r" % string)
+    year, month, day, hour, minute = map(
+        int, m.group("year", "month", "day", "hour", "minute"))
+    second = 0
+    microsecond = 0
+    s = m.group("second")
+    if s:
+        try:
+            second = int(s)
+        except ValueError:
+            seconds = float(s)
+            second = int(seconds)
+            # We figure out microseconds this way to avoid floating-point
+            # issues.  Anything smaller than one microsecond is simply thrown
+            # away.
+            fractional = s.split(".")[1]
+            while len(fractional) < 6:
+                fractional += "0"
+            fractional = fractional[:6]
+            microsecond = int(fractional)
+
+    if m.group("tzhour"):
+        tzhour, tzmin = map(int, m.group("tzhour", "tzmin"))
+        offset = (tzhour * 60) + tzmin
+        if m.group("tzdir") == "-":
+            offset *= -1
+        if offset:
+            tzinfo = pytz.FixedOffset(offset)
+            dt = datetime.datetime(
+                year, month, day, hour, minute, second, microsecond,
+                tzinfo=tzinfo)
+            return dt.astimezone(pytz.UTC)
+
+    return datetime.datetime(
+        year, month, day, hour, minute, second, microsecond,
+        tzinfo=pytz.UTC)


Property changes on: zc.iso8601/branches/dev/src/zc/iso8601/parse.py
___________________________________________________________________
Name: svn:mime-type
   + text/x-python
Name: svn:eol-style
   + native

Added: zc.iso8601/branches/dev/src/zc/iso8601/tests.py
===================================================================
--- zc.iso8601/branches/dev/src/zc/iso8601/tests.py	                        (rev 0)
+++ zc.iso8601/branches/dev/src/zc/iso8601/tests.py	2008-05-12 21:40:38 UTC (rev 86668)
@@ -0,0 +1,24 @@
+##############################################################################
+#
+# Copyright (c) 2008 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.
+#
+##############################################################################
+"""\
+Test harness for zc.iso8601.
+
+"""
+__docformat__ = "reStructuredText"
+
+from zope.testing import doctest
+
+
+def test_suite():
+    return doctest.DocFileSuite("README.txt")


Property changes on: zc.iso8601/branches/dev/src/zc/iso8601/tests.py
___________________________________________________________________
Name: svn:mime-type
   + text/x-python
Name: svn:eol-style
   + native



More information about the Checkins mailing list