Commits

Matthew Schinckel committed f1684ea

Added formatter.
Split out duration_parts() function.
Allow the leading P to be supplied on a parse_duration call.

Comments (0)

Files changed (5)

 Changelog:
     
     0.2a  - Initial support for duration data (excluding year/month).
+          - Initial support for formatting objects.
     
     0.1.6 - Allow for a date or datetime object to be passed to parse.
 	

iso8601/__init__.py

-from parser import parse
+from parser import parse
+from formatter import format

iso8601/formatter.py

+import datetime
+
+def format(obj):
+    if isinstance(obj, datetime.datetime):
+        return format_datetime(obj)
+    if isinstance(obj, datetime.timedelta):
+        return format_timedelta(obj)
+    if isinstance(obj, datetime.time):
+        return format_time(obj)
+    if isinstance(obj, datetime.date):
+        return format_date(obj)
+
+def format_datetime(obj):
+    return format_date(obj) + 'T' + format_time(obj)
+
+def format_date(obj):
+    return obj.strftime("%Y-%m-%d")
+
+def format_time(obj):
+    return obj.strftime("%H:%M:%S")
+
+def format_timedelta(obj):
+    parts = ["P"]
+    if obj.days / 7:
+        parts.append(str(obj.days / 7) + "W")
+        obj -= datetime.timedelta(days=7 * (obj.days / 7))
+    if obj.days:
+        parts.append(str(obj.days) + "D")
+        obj -= datetime.timedelta(days=obj.days)
+    if obj.seconds:
+        parts.append("T")
+        if obj.seconds / 3600:
+            parts.append(str(obj.seconds / 3600) + "H")
+            obj -= datetime.timedelta(seconds=3600 * (obj.seconds / 3600))
+        if obj.seconds / 60:
+            parts.append(str(obj.seconds / 60) + "M")
+            obj -= datetime.timedelta(seconds=60 * (obj.seconds / 60))
+        if obj.seconds:
+            parts.append(str(obj.seconds) + "S")
+    
+    return "".join(parts)

iso8601/parser.py

 def parse_time(time):
     pass
 
+# TODO Allow least significant to be a float.
 duration_regex = re.compile(
-    r'^((?P<years>\d+)Y)?'
+    r'^P?'
+    r'((?P<years>\d+)Y)?'
     r'((?P<months>\d+)M)?'
     r'((?P<weeks>\d+)W)?'
     r'((?P<days>\d+)D)?'
     r'((?P<seconds>\d+)S)?'
     r')?$'
 )
-def parse_duration(duration):
+
+def duration_parts(duration):
     data = duration_regex.match(duration)
     if not data or duration[-1] == 'T':
         raise ValueError("'P%s' does not match ISO8601 format" % duration)
-    data = {k:int(v) for k,v in data.groupdict().items() if v}
+    return {k:int(v) for k,v in data.groupdict().items() if v and int(v)}
+
+def parse_duration(duration):
+    data = duration_parts(duration)
     if 'years' in data or 'months' in data:
         raise ValueError('Year and month values are not supported in python timedelta')
     return datetime.timedelta(**data)
 
 setup(
     name = "iso-8601",
-    version = "0.2a",
+    version = "0.2a3",
     description = "Flexible ISO 8601 parser: pass in a valid ISO 8601 string, and a datetime object will be returned.",
     url = "http://hg.schinckel.net/iso-8601/",
     author = "Matthew Schinckel",
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.