parse_interval ignoring hours and shorter durations

Issue #4 resolved
Jan Vlčinský created an issue

If start date-time specifies hours, it works fine:

>>> import aniso8601
>>> aniso8601.interval.parse_interval("2014-11-12T12/PT1H")
(datetime.datetime(2014, 11, 12, 12, 0),
 datetime.datetime(2014, 11, 12, 13, 0))

If the start of interval uses only date format, adding days works well: >>> aniso8601.interval.parse_interval("2014-11-12/P1D") (datetime.date(2014, 11, 12), datetime.date(2014, 11, 13))

However, adding hours (or minutes/seconds) to starting date always returns date, thus ignoring hours/minuts/seconds:

>>> aniso8601.interval.parse_interval("2014-11-12/PT1H")
(datetime.date(2014, 11, 12), datetime.date(2014, 11, 12))

It seems, like if only date is used, whole dates are always result and rest is ignored. E.g. adding 48 hours to a date works well:

>>> aniso8601.interval.parse_interval("2014-11-12/PT48H")
(datetime.date(2014, 11, 12), datetime.date(2014, 11, 14))

But as it always retuns datetime.date, adding 54 hours gives the same result:

>>> aniso8601.interval.parse_interval("2014-11-12/PT54H")
(datetime.date(2014, 11, 12), datetime.date(2014, 11, 14))

I am not sure, if this is correct behaviour or not. To me, it was surprising and unexpected.

Options are:

  • modify the code to always return datetime.datetime thus reflecting hours/minutes/seconds even when added to datetime.date start.
  • explain, that current behaviour is correct.
    • explanatory note in documentation would be helpful
    • consider raising exception or issuing a warning, when duration contains fraction of days and is added to datetime.date

Comments (3)

  1. Brandon Nielsen repo owner

    I can confirm this as a bug. Page 22 of the ISO8601 spec calls out both intervals and durations having a resolution of less than a day (as you expected).

  2. Brandon Nielsen repo owner

    As of 0.84, which I just pushed to PyPI, I consider this fixed.

    I now promote the 'terminal' of an interval to a datetime if required by the duration part of an interval. For example:

    >>> aniso8601.parse_interval('2014-11-12/PT4H54M6.5S')
    (datetime.date(2014, 11, 12), datetime.datetime(2014, 11, 12, 4, 54, 6, 500000))
    

    This also works going the other way:

    >>> aniso8601.parse_interval('PT4H54M6.5S/2014-11-12')
    (datetime.date(2014, 11, 12), datetime.datetime(2014, 11, 11, 19, 5, 53, 500000))
    

    This was done to stay consistent with the behavior in previous versions where durations are specified with a date and a date time, for example:

    >>> aniso8601.parse_interval('1980-03-05/1981-04-05T01:01:00')
    (datetime.date(1980, 3, 5), datetime.datetime(1981, 4, 5, 1, 1))
    

    The behavior was chosen to not give the impression that a datetime was parsed from an interval that only specifies a date. This does limit the ability to use the sorted built-in on intervals of this type, but it's a tradeoff I'm willing to make for the logical consistency.

  3. Log in to comment