go: time: RFC3339 time.Parse can not parse string that come from time.Format

Please answer these questions before submitting your issue. Thanks!

What did you do?

ttps://play.golang.org/p/BItq172M-_ The bad time string “0007-05-31T3:50:00+99:80”

What did you expect to see?

0001-01-01 00:00:00 +0000 UTC xxx some error

What did you see instead?

0007-05-31 03:50:00 +10020 +10020 <nil>
0007-05-31T03:50:00+100:20
0001-01-01 00:00:00 +0000 UTC parsing time "0007-05-31T03:50:00+100:20" as "2006-01-02T15:04:05Z07:00": cannot parse "+100:20" as "Z07:00"

Because the RFC3339 parse/format is using in json. This may curse some crashes with special user input and developer assumes that json.Unmarshal is not return an error equals to json.Unmarshal/json.Marshal/json.Unmarshal will not return an error

This string is found by using https://github.com/dvyukov/go-fuzz

About this issue

  • Original URL
  • State: open
  • Created 7 years ago
  • Reactions: 3
  • Comments: 22 (8 by maintainers)

Commits related to this issue

Most upvoted comments

https://play.golang.org/p/2xDQsXxYcxe

Even the layout itself is not a valid value,

time.Parse(time.RFC3339, time.RFC3339)
// parsing time "2006-01-02T15:04:05Z07:00": extra text: 07:00

I would like to add my experience to this. Would really love to see a fix for this. Many systems (including fmt.Println(someTime) output the time as YYYY-MM-DDTHH:MM:SS.sss+HHMM (note no colon on offset).

The RFC 3339 spec notes that the colon is optional for the offset (see https://tools.ietf.org/html/rfc3339#appendix-A). Because the json.Unmarshal() automatically uses the RFC3339 as the format, this prevents Go from parsing many versions of the standard timestamp format in its acceptance of json.

All of these should be valid: “2006-01-02T15:04:05+0000” “2006-01-02T15:04:05-0000”

I’m wonder if supporting the colon in the offset being optional really requires waiting for Go 2?

https://play.golang.org/p/2xDQsXxYcxe

Even the layout itself is not a valid value,

time.Parse(time.RFC3339, time.RFC3339)
// parsing time "2006-01-02T15:04:05Z07:00": extra text: 07:00

This is expected and documented: " // Some valid layouts are invalid time values, due to format specifiers // such as _ for space padding and Z for zone information. // For example the RFC3339 layout 2006-01-02T15:04:05Z07:00 // contains both Z and a time zone offset in order to handle both valid options: // 2006-01-02T15:04:05Z // 2006-01-02T15:04:05+07:00 " Ref https://pkg.go.dev/time#Parse

I’ve just been hit by this issue.

I would expect "2018-01-16T05:15:37Z" to be valid input and handled by time.RFC3339, but "2018-01-16T5:15:37Z" is not valid due to missing leading zero on the Hour.

It seems rather inconsistent…

  • Month with 01 - Expects leading zeros
  • Hour with 3 formatter value - 12H with optional leading zeros
  • Hour with 03 formatter value - 12H with mandatory leading zeros
  • Hour with 15 formatter value - 24H with optional leading zeros
  • 24H with mandatory leading zeros use case is missing ?

I’m going to put out perhaps a somewhat unpopular opinion, but perhaps the designers of Golang and the core libs to re-assess whether the “by example” format string that Go uses is actually fit for purpose.

I know we can have arguments about what is more ‘understandable’, and I don’t contest that perhaps some people find this easier, and others find the approaches used in other languages (like C, Swift, Ruby etc).

BUT, it seems that the Go approach just is not able to parse all scenarios using the Time functionality. It forces you to perform direct string parsing instead. I know this isn’t going to happen for Go2, but maybe future releases could consider deprecating and replacing the “by example” way of doing things???

@seankhliao That is unfortunate because it makes testing time structure difficult since any deep equals check of the time struct before and after the marshaling will not be equal.

@brian-brazil I think that is behaviour as expected. RFC3339 assumes that:

All dates and times are assumed to be in the “current era”, somewhere between 0000AD and 9999AD.