Skip to content

time: documentation shows incorrect formatting of RFC3339 that does not parse #22135

@joelpresence

Description

@joelpresence

Please answer these questions before submitting your issue. Thanks!

What version of Go are you using (go version)?

go version go1.8.3 darwin/amd64

Does this issue reproduce with the latest release?

Yes, as far as I know.

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/joel/go"
GORACE=""
GOROOT="/usr/local/go"
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/mz/tzh0vwxd08jgh0lx24v39gx40000gn/T/go-build013964967=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
PKG_CONFIG="pkg-config"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"

What did you do?

Look at the documentation for the go time package at https://golang.org/pkg/time/#pkg-constants where you'll see:

const (
...
RFC3339     = "2006-01-02T15:04:05Z07:00"
...
)

Now, run the following program:

package main

import (
	"fmt"
	"time"
)

func main() {
	// From https://golang.org/pkg/time/#pkg-constants
	//
	//     RFC3339     = "2006-01-02T15:04:05Z07:00"
	timeStr := "2006-01-02T15:04:05Z07:00"

	// time.Parse fails on the sentinel example given in godoc
	parsed, errParsed := time.Parse(timeStr, time.RFC3339)
	fmt.Printf("parsed %v errParsed %v\n", parsed, errParsed)

	loc, errLoc := time.LoadLocation("MST")
	fmt.Printf("loc %v errLoc %v\n", loc, errLoc)

	t := time.Date(2006, 1, 2, 15, 4, 5, 0, loc)
	tStr := t.Format(time.RFC3339)

	fmt.Printf("tStr %v timeStr %v tStr == timeStr %v\n", tStr, timeStr, tStr == timeStr)

	// time.Parse fails on its own output that was just created
	parsed, errParsed = time.Parse(tStr, time.RFC3339)
	fmt.Printf("parsed %v errParsed %v\n", parsed, errParsed)
}

You will get the following output:

parsed 0001-01-01 00:00:00 +0000 UTC errParsed parsing time "2006-01-02T15:04:05Z07:00": extra text: 07:00
loc MST errLoc <nil>
tStr 2006-01-02T15:04:05-07:00 timeStr 2006-01-02T15:04:05Z07:00 tStr == timeStr false
parsed 0001-01-01 00:00:00 +0000 UTC errParsed parsing time "2006-01-02T15:04:05Z07:00" as "2006-01-02T15:04:05-07:00": cannot parse "" as "-07:00"

This is a clear and strong violation of the principle of least surprise. It is a strong expectation of go coders that the following loop will work:

var t time.Time = ...

// Format your time to a string
tString := t.Format(time.RFC3339)

// Your formatted time should ALWAYS parse successfully
// using the format you just formatted it with.
parsed, errParsed := time.Parse(time.RFC3339)

// errParsed MUST be nil here
// parsed should NOT be nil and SHOULD be equivalent to t

If I format a time into a string according to some format F, then I attempt to parse that untouched string using the format F I should ALWAYS be able to parse it back into the original time (or at least something equivalent where Parse(t.Format(F), F) does NOT error.

If possible, provide a recipe for reproducing the error.
A complete runnable program is good.
A link on play.golang.org is best.

What did you expect to see?

Parsing a time string you just formatted should successfully parse.

What did you see instead?

Parsing a time string you just formatted errors. Moreover, the godoc documentation for RFC3339 shows a sentinel format example that does not match actual output.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions