Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

time: Location detect unknown offset #36366

Closed
icholy opened this issue Jan 2, 2020 · 1 comment
Closed

time: Location detect unknown offset #36366

icholy opened this issue Jan 2, 2020 · 1 comment

Comments

@icholy
Copy link

icholy commented Jan 2, 2020

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

go version go1.13 linux/amd64

Does this issue reproduce with the latest release?

Yes

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

go env Output
GO111MODULE=""
GOARCH="amd64"
GOBIN="/home/icholy/go/bin"
GOCACHE="/home/icholy/.cache/go-build"
GOENV="/home/icholy/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/icholy/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build269389064=/tmp/go-build -gno-record-gcc-switches"

What did you do?

package main

import (
	"fmt"
	"time"
)

func main() {
	t, err := time.Parse(time.RFC1123, "Wed, 25 Dec 2019 20:09:20 EST")
	if err != nil {
		panic(err)
	}
	fmt.Println(t.Zone())
}

https://play.golang.org/p/k6d-epEgF-1

What did you expect to see?

A way to detect between a zero offset and an unknown offset. I want to detect/block unknown timezone names before they enter the database with the wrong offset.

What did you see instead?

go/src/time/format.go

Lines 1174 to 1179 in a4c579e

// Otherwise, create fake zone with unknown offset.
if len(zoneName) > 3 && zoneName[:3] == "GMT" {
offset, _ = atoi(zoneName[3:]) // Guaranteed OK by parseGMT.
offset *= 3600
}
t.setLoc(FixedZone(zoneName, offset))

@icholy icholy changed the title time.Localtion detect unknown offset time.Location detect unknown offset Jan 2, 2020
@toothrot toothrot changed the title time.Location detect unknown offset time: Location detect unknown offset Jan 7, 2020
@toothrot
Copy link
Contributor

toothrot commented Jan 7, 2020

The current design of Parse, as I understand it, purposely leaves this situation up to the user to decide, as there are tradeoffs based on what you expect from your data for this time format.

https://pkg.go.dev/time?tab=doc#Parse

If the zone abbreviation is unknown, Parse records the time as being in a fabricated location with the given zone abbreviation and a zero offset. This choice means that such a time can be parsed and reformatted with the same layout losslessly, but the exact instant used in the representation will differ by the actual zone offset. To avoid such problems, prefer time layouts that use a numeric zone offset, or use ParseInLocation.

Strictly speaking, for your example of Wed, 25 Dec 2019 20:09:20 EST, a name was provided and an offset wasn't, so this is working as intended.

This is complicated by the RFC1123 format, as documented in time:

https://pkg.go.dev/time?tab=doc#pkg-constants

Note that the RFC822, RFC850, and RFC1123 formats should be applied only to local times. Applying them to UTC times will use "UTC" as the time zone abbreviation, while strictly speaking those RFCs require the use of "GMT" in that case. In general RFC1123Z should be used instead of RFC1123 for servers that insist on that format, and RFC3339 should be preferred for new protocols. RFC3339, RFC822, RFC822Z, RFC1123, and RFC1123Z are useful for formatting; when used with time.Parse they do not accept all the time formats permitted by the RFCs.

If you're stuck with RFC1123, you'll have to use ParseInLocation to handle the specific edge case of your data, like https://play.golang.org/p/qfqGisQqhrc

Let me know if there's a good suggestion to work around this, but I don't see a better way of the standard library catering to every format.

@icholy icholy closed this as completed Jan 7, 2020
@golang golang locked and limited conversation to collaborators Jan 6, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants