qri-io / jsonschema

golang implementation of https://json-schema.org drafts 7 & 2019-09
MIT License
461 stars 54 forks source link

Date-time parsing is too strict #92

Closed cpence closed 2 years ago

cpence commented 3 years ago

Issue

What did you do?

Try parsing a JSON file using a date-time that is valid according to RFC3339, but truncated. For example, 2021-02-22 is a valid RFC3339 date-time.

What happened?

The following error will be generated:

file: /attribute: "2021-02-22" invalid date-time: date-time incorrectly Formatted: parsing time "2021-02-22" as "2006-01-02T15:04:05Z07:00": cannot parse "" as "T"

What did you expect to happen?

This attribute should validate correctly.

Do you have a suggested fix?

Simply passing Golang's time.RFC3339 to time.parse is not sufficient to determine whether or not a date is compatible with RFC3339, because it passes only when a complete date-time is found, and the RFC allows for partial/truncated dates, assuming each of the provided fields is in order and correct.

I've implemented a workaround that involves checking against all of the following formatting strings; if any of them pass, it should be a valid RFC3339 date:

func rfc3339Parts() []string {
    return []string{
        "2006-01-02T15:04:05Z07:00",
        "2006-01-02T15:04:05",
        "2006-01-02T15:04",
        "2006-01-02T15",
        "2006-01-02",
        "2006-01",
        "2006",
    }
}
handrews commented 2 years ago

If you want to allow 2021-02-22 you should use "format": "date", not "format": "date-time"

cpence commented 2 years ago

Old bug, so I had to go read the new versions of the spec to remind myself what's up.

Quoting from the JSON Schema spec:

   date-time:  A string instance is valid against this attribute if it
      is a valid representation according to the "date-time' ABNF rule
      (referenced above)

   date:  A string instance is valid against this attribute if it is a
      valid representation according to the "full-date" ABNF rule
      (referenced above)

   time:  A string instance is valid against this attribute if it is a
      valid representation according to the "full-time" ABNF rule
      (referenced above)

So, as it turns out, only full date-times, full dates, and full times are supported by the spec. Short forms should not be supported. So current behavior is correct here; my mistake!

cpence commented 2 years ago

(side note if anybody stumbles into this issue: this means that technically, when people say that "date-time" in JSON Schema is "an RFC 3339 date-time," that's not entirely accurate! It's a complete RFC 3339 date-time, with only fractional seconds optional.)