Skip to content

time: enforce strict parsing for RFC3339 for Time.Unmarshal  #54580

@dsnet

Description

@dsnet

When calling:

time.Parse(time.RFC3339, s)

one would expect that this strictly parses s according to RFC 3339 as the constant suggests.
This parses all valid RFC 3339 timestamps (except those with leap-seconds),
however it fails to reject certain inputs that are not valid RFC 3339.

Parse differs from the RFC 3339 syntax in the following ways:

  1. Parse permits the hour fields to only have one digit, while RFC 3339 requires that it always be two digits.

  2. Parse permits a comma separator between seconds and sub-seconds, while RFC 3339 only permits a period.

  3. Parse permits time zone offsets with any range of values, while RFC 3339 limits hours to be less than 24 and minutes to be less than 60.

    • For example, 0000-01-01T00:00:00+24:60 is considered valid, when it should not be.

In all situations, the time format template provides no way to strictly parse RFC 3339.

Since we can't change the text template meaning of "15" and ".",
nor can we change the constant value of RFC3339 or RFC3339Nano,
I propose that we special-case Parse to use strict parsing when handling a format template
identical to RFC3339 and RFC3339Nano.

Justification for this special-casing:

  • RFC 3339 is by far the most popular time representation.
  • RFC 3339 exists because ISO 8601 had too many alternate representations.
    Being loose in what Go considers "valid" RFC 3339 is going against the goal of RFC 3339.

\cc @robpike

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions