Why can't go parse the time represented by the provided formats?

10,232

Solution 1

The time.RFC3339 format is a case where the format string itself isn't a valid time. You can't have a Z and an offset in the time string, but the format string has both because the spec can contain either type of timezone specification.

Both of these are valid RFC3339 times:

"2015-09-15T14:00:12-00:00"
"2015-09-15T14:00:13Z"

And the time package needs to be able to parse them both using the same RFC3339 format string.

Solution 2

As noted, 2006-01-02T15:04:05Z07:00 is an invalid IETF RFC-3339 time format. Here's an explanation.

The reason you cannot have both Z and an offset is that they are both ways to represent a time offset. Z is equivalent to +00:00 indicating a zero hour/minute offset, or no offset. You cannot say both +00:00 offset and +07:00 offset in the same time representation.

The following is the Z definition in the RFC-3339 Section 2:

https://www.rfc-editor.org/rfc/rfc3339#section-2

Z  A suffix which, when applied to a time, denotes a UTC
   offset of 00:00; often spoken "Zulu" from the ICAO
   phonetic alphabet representation of the letter "Z".

Of note, while Z is equivalent to +00:00, they are both different from -00:00 which indicates known UTC time with an unknown offset, as described in RFC-3339 Section 4.3:

https://www.rfc-editor.org/rfc/rfc3339#section-4.3

4.3. Unknown Local Offset Convention

   If the time in UTC is known, but the offset to local time is unknown,
   this can be represented with an offset of "-00:00".  This differs
   semantically from an offset of "Z" or "+00:00", which imply that UTC
   is the preferred reference point for the specified time.  RFC2822
   [IMAIL-UPDATE] describes a similar convention for email.
Share:
10,232
mdwhatcott
Author by

mdwhatcott

I'm a software developer at Clean Coders Studio (https://cleancoders.com/studio).

Updated on July 28, 2022

Comments

  • mdwhatcott
    mdwhatcott almost 2 years

    Consider this example:

    package main
    
    import (
        "fmt"
        "time"
    )
    
    func main() {
        fmt.Println(time.Parse(time.RFC3339, time.RFC3339))
    }
    

    The output is:

    0001-01-01 00:00:00 +0000 UTC parsing time "2006-01-02T15:04:05Z07:00": extra text: 07:00
    

    Why can't time.Parse() handle a layout as a value? What's missing here?


    UPDATE: Cutting off the time zone value (but not the 'Z' delimiting the time from the zone) fixes it:

    fmt.Println(time.Parse(time.RFC3339, "2015-09-15T11:50:00Z"))
    

    Why can't time.Parse() handle time zone info when using time.RFC3339 as the layout string?

    http://play.golang.org/p/p3fHfJNHVK


    UPDATE: JimB's answer led me to read from RFC3339 and I found these examples that clarify further:

    Here are some examples of Internet date/time format.

    1985-04-12T23:20:50.52Z

    This represents 20 minutes and 50.52 seconds after the 23rd hour of April 12th, 1985 in UTC.

    1996-12-19T16:39:57-08:00

    This represents 39 minutes and 57 seconds after the 16th hour of December 19th, 1996 with an offset of -08:00 from UTC (Pacific Standard Time). Note that this is equivalent to 1996-12-20T00:39:57Z in UTC.

  • Bernard Halas
    Bernard Halas over 2 years
    Based on your response it seems the example in the package documentation for RFC3339 is wrong. pkg.go.dev/time#pkg-constants