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: ParseInLocation incorrect after 2038 #25343

Open
jimcheetham opened this Issue May 10, 2018 · 2 comments

Comments

Projects
None yet
3 participants
@jimcheetham

jimcheetham commented May 10, 2018

Please answer these questions before submitting your issue. Thanks!

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

go1.10.2

Does this issue reproduce with the latest release?

yes

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

using https://play.golang.org

What did you do?

Used time.ParseInLocation to grok a time from "Europe/London"

Noticed that the resulting time switched from BST (appropriate for the month/day used) to GMT after 2038

package main

import "fmt"
import "time"

func main() {

	var timet = "2037-05-06 00:54:39"
	var timef = "2038-05-06 00:54:39"

	tz, _ := time.LoadLocation("Europe/London")

	tinz, _ := time.ParseInLocation("2006-01-02 15:04:05", timet, tz)
	finz, _ := time.ParseInLocation("2006-01-02 15:04:05", timef, tz)

	fmt.Printf("TimeT: %v\nTimeF: %v\n", tinz, finz)
	
}

https://play.golang.org/p/5oMrjFT_3F1

What did you expect to see?

TimeT: 2037-05-06 00:54:39 +0100 BST
TimeF: 2038-05-06 00:54:39 +0100 BST

The 2038 date as BST, the same as the 2037 date. See this example of GNU coreutils 8.26 date() :

$ TZ="Europe/London" date -d '2018-05-06 00:54:39'
Sun May  6 00:54:39 BST 2018
$ TZ="Europe/London" date -d '3304-05-06 00:54:39'
Tue May  6 00:54:39 BST 3304

What did you see instead?

TimeT: 2037-05-06 00:54:39 +0100 BST
TimeF: 2038-05-06 00:54:39 +0000 GMT

@ianlancetaylor ianlancetaylor changed the title from time.ParseInLocation incorrect after 2038 to time: ParseInLocation incorrect after 2038 May 10, 2018

@ianlancetaylor ianlancetaylor added this to the Go1.12 milestone May 10, 2018

@mdcnz

This comment has been minimized.

mdcnz commented May 14, 2018

GMT = UTC+0, Greenwich Mean Time
BST = UTC+1, British Summer Time, daylight saving

Times after 2038 seem to stop adjusting to or from daylight saving zones, because the time exceeds the available timezone transitions.

Instead, the latest available zone transition is returned. It may or may not be in daylight saving. See Location.lookup.

Zone transitions are derived either from the system timezone db (eg /etc/timezone) or from a local copy (eg, $GOROOT/lib/time/zoneinfo.zip). This can be selected by the ZONEINFO env var.

Zone transitions are parsed in LoadLocationFromTZData

	// If version == 2 or 3, the entire file repeats, this time using
	// 8-byte ints for txtimes and leap seconds.
	// We won't need those until 2106.

That code comment might not be correct. The year 2106 is the limit of unsigned 32 bit integer seconds since the epoch, but the timezone information format states These 32-bit values are limited to representing times no later than 19 January, 2038 03:14:07 UTC. (max signed 32 bit int since unix epoch). Looks like zone transitions beyond 2038 won't be parsed, even if available in source timezone data.

Also, extended data is excluded from Go's zoneinfo.zip, to reduce file size. In lib/time/update.bash:

# Turn off 64-bit output in time zone files.
# We don't need those until 2037.
perl -p -i -e 's/pass <= 2/pass <= 1/' zic.c
@jimcheetham

This comment has been minimized.

jimcheetham commented Jun 3, 2018

IANA's documentation (https://data.iana.org/time-zones/theory.html) mentions the issue, with a presumption that 64-bit values are expected:

The tz code attempts to support all the time_t implementations allowed by POSIX. The time_t type represents a nonnegative count of seconds since 1970-01-01 00:00:00 UTC, ignoring leap seconds. In practice, time_t is usually a signed 64- or 32-bit integer; 32-bit signed time_t values stop working after 2038-01-19 03:14:07 UTC, so new implementations these days typically use a signed 64-bit integer.

Is it the feeling here that Go should be using 64-bit values for TZ-related time?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment