[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