Sub-microsecond precision is lost when parsing Y, M, D, W, h, m, s components
Continuation of issue #10. In issue #10, we truncated second components to microsecond resolution in the default PythonTimeBuilder
, punting support for higher resolutions to alternative builders.
However, other components support decimal precision as well, showing the same erroneous behaviors when using sub-microsecond precision is attempted.
0.000000016667 minutes in a microsecond:
>>> aniso8601.parse_duration('PT0.00000000999M')
datetime.timedelta(0, 0, 1)
>>> aniso8601.parse_time('14:43.999999997')
datetime.time(14, 44)
Same issue with hours:
>>> aniso8601.parse_time('14.99999999997')
datetime.time(15, 0)
Year rollover (365 days per year, rolls over to 2000Y):
>>> aniso8601.parse_duration('P1999.99999999999997Y')
datetime.timedelta(730000)
Month rollover (30 days per month, rolls over to 2M):
>>> aniso8601.parse_duration('P1999Y1.9999999999997M')
datetime.timedelta(729695)
Day rollover to 2D:
>>> aniso8601.parse_duration('P1999Y1M1.99999999997D')
datetime.timedelta(729667)
Week rollover to 2W:
>>> aniso8601.parse_duration('P1.9999999999997W')
datetime.timedelta(14)
The fix for these is less clear since they do not divide evenly into a microsecond, so we can't simply truncate to maximum supported precision unless we're okay with throwing away maximum possible resolution.
Comments (6)
-
reporter -
reporter It should be noted that the above issues match the behavior of the Python builtins:
>>> datetime.timedelta(minutes=0.00000000999).microseconds 1 >>> datetime.timedelta(minutes=43.999999997).seconds 2640 >>> (datetime.datetime(1999, 1, 1) + datetime.timedelta(hours=14.99999999997)).hour 15 >>> datetime.timedelta(days=1999.99999999999997 * 365.0).days 730000 >>> datetime.timedelta(days=1.99999999999997 * 30.0).days 60 >>> datetime.timedelta(days=1.999999999997).days 2 >>> datetime.timedelta(weeks=1.9999999999997).days 14
Note the months and day tests required an extra digit of precision since there's no years involved.
-
reporter The issue-21 branch contains fixes for this, they are currently on track to land with 5.0.0 later this year.
-
reporter There is now a matching aniso8601-5.0.0-issue-21 branch for relativetimebuilder.
-
reporter Fixes merged into 5.0.0.
-
reporter - changed status to resolved
5.0.0 has been released.
- Log in to comment
The easiest solution may be to expand the fractional component to seconds, truncate to microsecond precision, then continue building.