time: deal a bit better with time zones in Parse
* Document Parse's zone interpretation.
* Add ParseInLocation (API change).
* Recognize "wrong" time zone names, like daylight savings time in winter.
* Disambiguate time zone names using offset (like winter EST vs summer EST in Sydney).
The final two are backwards-incompatible changes, but I believe
they are both buggy behavior in the Go 1.0 versions; the old results
were more wrong than the new ones.
Fixes #3604.
Fixes #3653.
Fixes #4001.
R=adg
CC=golang-dev
https://golang.org/cl/7288052
diff --git a/src/pkg/time/zoneinfo.go b/src/pkg/time/zoneinfo.go
index 116d343..c44477f 100644
--- a/src/pkg/time/zoneinfo.go
+++ b/src/pkg/time/zoneinfo.go
@@ -145,15 +145,36 @@
}
// lookupName returns information about the time zone with
-// the given name (such as "EST").
-func (l *Location) lookupName(name string) (offset int, isDST bool, ok bool) {
+// the given name (such as "EST") at the given pseudo-Unix time
+// (what the given time of day would be in UTC).
+func (l *Location) lookupName(name string, unix int64) (offset int, isDST bool, ok bool) {
l = l.get()
+
+ // First try for a zone with the right name that was actually
+ // in effect at the given time. (In Sydney, Australia, both standard
+ // and daylight-savings time are abbreviated "EST". Using the
+ // offset helps us pick the right one for the given time.
+ // It's not perfect: during the backward transition we might pick
+ // either one.)
+ for i := range l.zone {
+ zone := &l.zone[i]
+ if zone.name == name {
+ nam, offset, isDST, _, _ := l.lookup(unix - int64(zone.offset))
+ if nam == zone.name {
+ return offset, isDST, true
+ }
+ }
+ }
+
+ // Otherwise fall back to an ordinary name match.
for i := range l.zone {
zone := &l.zone[i]
if zone.name == name {
return zone.offset, zone.isDST, true
}
}
+
+ // Otherwise, give up.
return
}