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

Closed
jimcheetham opened this issue May 10, 2018 · 7 comments

Comments

Projects
None yet
5 participants
@jimcheetham
Copy link

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 time.ParseInLocation incorrect after 2038 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.

Copy link

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.

Copy link
Author

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?

@odeke-em

This comment has been minimized.

Copy link
Member

commented Feb 4, 2019

Thank you for the report @jimcheetham and welcome to the Go project! Thank you too @mdcnz for the discussion and debugging.

So we didn't get to this during Go1.12 but I'll punt it for investigation for Go1.13 and @mdcnz if you'd like to take a deeper stab at this during Go1.13, all yours :) I'll also page some other folks too @robpike @ALTree @ianlancetaylor

@odeke-em odeke-em modified the milestones: Go1.12, Go1.13 Feb 4, 2019

@iWdGo

This comment has been minimized.

Copy link
Contributor

commented Apr 8, 2019

Gregorian 2038 is the maximum year reachable with the 32-bit signed version from epoch. The tz database used by Go and others introduces issues beyond 2038 and falls back on defaults during that year for daylight saving time between others. This is a known effect as icann mentions. Specifically for Daylight Saving Time (anywhere), its future is not definite beyond 2038. Current behavior seems appropriate.

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Apr 8, 2019

I think that the Go library is correctly reporting what the TZ database supports. The Go library does now use the extended data, for #30099. I don't think there is anything to do here on the Go side. Please comment if you disagree.

@jimcheetham

This comment has been minimized.

Copy link
Author

commented Apr 9, 2019

Are you suggesting that the changes referred to in #30099 (https://golang.org/cl/161202) have caused an improvement in this situation? If so, excellent :-)

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Apr 10, 2019

They may have improved the situation. I don't know for sure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.