danielrichman / strict-rfc3339

Strict, simple, lightweight RFC3339 functions
GNU General Public License v3.0
31 stars 13 forks source link

Examples from RFC3339 spec don't validate #4

Closed hajapy closed 1 year ago

hajapy commented 6 years ago

I was recently trying to use this library as part of jsonschema "date-time" format validation and was writing tests based on the examples in the RFC3339 spec: https://tools.ietf.org/html/rfc3339#section-5.8

Here is what I get:

In [1]: import strict_rfc3339

In [2]: strict_rfc3339.validate_rfc3339("1985-04-12T23:20:50.52Z")
Out[2]: True

In [3]: strict_rfc3339.validate_rfc3339("1996-12-19T16:39:57-08:00")
Out[3]: True

In [4]: strict_rfc3339.validate_rfc3339("1990-12-31T23:59:60Z")
Out[4]: False

In [5]: strict_rfc3339.validate_rfc3339("1990-12-31T15:59:60-08:00")
Out[5]: False

In [6]: strict_rfc3339.validate_rfc3339("1937-01-01T12:00:27.87+00:20")
Out[6]: True

Should those 2 cases really fail to validate?

danielrichman commented 6 years ago

Your complaint is understandable. See: https://github.com/danielrichman/strict-rfc3339#caveats and https://github.com/danielrichman/strict-rfc3339#notes item 3:

[Unix] Timestamps don't support leap seconds: a day is always 86400 "long". Also, validating leap seconds is particularly fiddly, because not only do you need some data, but it must be kept up to date. For this reason, strict_rfc3339 does not support leap seconds: in validation, seconds == 60 or seconds == 61 is rejected. In the case of reverse leap seconds, calendar.timegm will blissfully accept it. The result would be about as correct as you could get.

https://github.com/danielrichman/strict-rfc3339/blob/78afdfc346293cfe934c3fc80c347e69691ffd05/strict_rfc3339.py#L63

I guess it's not clear to me what it means for a RFC3339 string to be 'valid'. The example you quote, for example, is not actually a moment in time: there was no leap second at the start of 1991, I believe?

All that said, if you still want this, maybe we should add an extra argument to each of the functions, that specifies how it should behave if there is a leap second. What do you think?

hajapy commented 6 years ago

I see, I should have looked more closely. My surprise was mostly in that examples taken verbatim for the spec did not validate, but it's clear those are special edge cases that even the python stdlib doesn't support. I don't think anything needs to change, frankly, though it is just an unfortunate circumstance.

You may be interested to see that there is some upstream work on parsing RFC3339 directly with datetime.datetime.fromisoformat that is being worked on for Py3.7: https://bugs.python.org/issue15873

It was also noted in the discussion there that leap seconds are not supported.

That said, I do believe there was a leap second at the start of 1991 (end of 1990) ;) https://www.ietf.org/timezones/data/leap-seconds.list