Edgewall Software

Opened 8 years ago

Closed 8 years ago

Last modified 8 years ago

#12377 closed defect (fixed)

iso8601 with high time resolution and no timezone leads strange timezone — at Version 8

Reported by: Jun Omae Owned by: Jun Omae
Priority: low Milestone: 1.0.11
Component: general Version:
Severity: minor Keywords:
Cc: Branch:
Release Notes:

Fix parse_date() returning incorrect timezone for iso8601 text with high time resolution.

API Changes:
Internal Changes:

Description

I noticed strange behaviors in parse_date() while adding unit tests in [9b9c8a56e/jomae.git].

$ ~/venv/trac/1.0.10/bin/python
Python 2.5.6 (r256:88840, Oct 21 2014, 22:26:35)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from trac.util.datefmt import parse_date, utc
>>> parse_date('2016-01-02T12:34:56.987654', utc)
datetime.datetime(2016, 1, 2, 12, 34, 56, 987654, tzinfo=<FixedOffset "UTC" 0:00:00>)
>>> parse_date('2016-01-02T12:34:56.9876543', utc)
datetime.datetime(2016, 1, 2, 12, 34, 56, 987650, tzinfo=<FixedOffset "None43:None" 19:00:00>)
>>> parse_date('2016-01-02T12:34:56.98765432', utc)
datetime.datetime(2016, 1, 2, 12, 34, 56, 987654, tzinfo=<FixedOffset "None32:None" 8:00:00>)
>>> parse_date('2016-01-02T12:34:56.987654321', utc)
datetime.datetime(2016, 1, 2, 12, 34, 56, 987650, tzinfo=<FixedOffset "None43:21" 19:21:00>)
>>> parse_date('2016-01-02T12:34:56.9876543210', utc)
datetime.datetime(2016, 1, 2, 12, 34, 56, 987654, tzinfo=<FixedOffset "None32:10" 8:10:00>)
>>> parse_date('2016-01-02T12:34:56.98765432109', utc)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "~/venv/trac/1.0.10/lib/python2.5/site-packages/trac/util/datefmt.py", line 615, in parse_date
    raise TracError(msg, _('Invalid Date'))
trac.core.TracError: "2016-01-02T12:34:56.98765432109" is an invalid date, or the date format is not known. Try "MM/dd/YY" or "YYYY-MM-DD" instead.

Change History (8)

comment:1 by Jun Omae, 8 years ago

Other issues:

  1. When minutes in timezone offset is omitted:
    >>> parse_date('2016-03-02T12:34:56-12')
    datetime.datetime(2016, 3, 2, 12, 34, 56, tzinfo=<FixedOffset "-12:None" -1 day, 12:00:00>)
    
  2. When timezone offset is 24:00, 48:00, …:
    >>> parse_date('2016-03-02T12:34:56-24:00')
    datetime.datetime(2016, 3, 2, 12, 34, 56, tzinfo=<FixedOffset "UTC" 0:00:00>)
    >>> parse_date('2016-03-02T12:34:56-48:00')
    datetime.datetime(2016, 3, 2, 12, 34, 56, tzinfo=<FixedOffset "UTC" 0:00:00>)
    >>> parse_date('2016-03-02T12:34:56-72:00')
    datetime.datetime(2016, 3, 2, 12, 34, 56, tzinfo=<FixedOffset "UTC" 0:00:00>)
    >>> parse_date('2016-03-02T12:34:56-96:00')
    datetime.datetime(2016, 3, 2, 12, 34, 56, tzinfo=<FixedOffset "UTC" 0:00:00>)
    
  3. When minutes of timezone offset is out of range:
    >>> parse_date('2016-03-02T12:34:56+00:99')
    datetime.datetime(2016, 3, 2, 12, 34, 56, tzinfo=<FixedOffset "+00:99" 1:39:00>)
    >>> parse_date('2016-03-02T12:34:56+00:60')
    datetime.datetime(2016, 3, 2, 12, 34, 56, tzinfo=<FixedOffset "+00:60" 1:00:00>)
    

comment:2 by Jun Omae, 8 years ago

Proposed changes in log:jomae.git@t12377.

comment:3 by Christian Boos, 8 years ago

Just something I spotted looking at [63b75491/jomae.git]: (\d\d):?(\d\d)? will also allow \d\d\d\d, which I think shouldn't be valid offset either. Perhaps use (\d\d)(?::(\d\d))? instead.

comment:4 by Jun Omae, 8 years ago

I think ISO 8601 allows +hhmm in timezone offset. See wikipedia:ISO_8601#Time_zone_designators and time-numoffset definition in rfc:3339#appendix-A.

comment:5 by Christian Boos, 8 years ago

OK, and of course only now I see the corresponding examples in the tests you added, please ignore my botched review ;-)

comment:6 by Jun Omae, 8 years ago

Yeah. Thanks for the looking! Ah, re pattern for iso8601 could be simple a bit.

     (                                       # timezone
         Z                                   #   Z
-      | (?:([-+])(\d\d):?(\d\d)?)           #   +hh:mm, -hh:mm, +hh, -hh
+      | ([-+])(\d\d):?(\d\d)?               #   ±hh:mm, ±hhmm, ±hh
     )?
Last edited 8 years ago by Jun Omae (previous) (diff)

comment:7 by Jun Omae, 8 years ago

Milestone: next-stable-1.0.x1.0.11
Owner: set to Jun Omae
Status: newassigned

comment:8 by Jun Omae, 8 years ago

Release Notes: modified (diff)
Resolution: fixed
Status: assignedclosed

Committed in [14596] and merged to trunk in [14597].

Note: See TracTickets for help on using tickets.