Commit 2951f909 authored by Florian Uekermann's avatar Florian Uekermann Committed by Brad Fitzpatrick

time: enable Location loading from user provided timezone data

The return values of the LoadLocation are inherently dependent
on the runtime environment. Add LoadLocationFromTZData, whose
results depend only on the timezone data provided as arguments.

Fixes #20629

Change-Id: I43b181f4c05c219be3ec57327540263b7cb3b2aa
Reviewed-on: https://go-review.googlesource.com/68890Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 9a14cd9e
......@@ -34,4 +34,5 @@ var (
GetMono = (*Time).mono
ErrLocation = errLocation
ReadFile = readFile
LoadTzinfo = loadTzinfo
)
......@@ -18,11 +18,11 @@ func initTestingZone() {
localLoc = *z
}
var origZoneSources = zoneSources
var OrigZoneSources = zoneSources
func forceZipFileForTesting(zipOnly bool) {
zoneSources = make([]string, len(origZoneSources))
copy(zoneSources, origZoneSources)
zoneSources = make([]string, len(OrigZoneSources))
copy(zoneSources, OrigZoneSources)
if zipOnly {
zoneSources = zoneSources[len(zoneSources)-1:]
}
......
......@@ -294,7 +294,7 @@ func LoadLocation(name string) (*Location, error) {
})
if *zoneinfo != "" {
if zoneData, err := loadTzinfoFromDirOrZip(*zoneinfo, name); err == nil {
if z, err := newLocationFromTzinfo(name, zoneData); err == nil {
if z, err := LoadLocationFromTZData(name, zoneData); err == nil {
return z, nil
}
}
......
......@@ -79,11 +79,12 @@ func byteString(p []byte) string {
var badData = errors.New("malformed time zone information")
// newLocationFromTzinfo returns the Location described by Tzinfo with the given name.
// The expected format for Tzinfo is that of a timezone file as they are found in the
// the IANA Time Zone database.
func newLocationFromTzinfo(name string, Tzinfo []byte) (*Location, error) {
d := dataIO{Tzinfo, false}
// LoadLocationFromTZData returns a Location with the given name
// initialized from the IANA Time Zone database-formatted data.
// The data should be in the format of a standard IANA time zone file
// (for example, the content of /etc/localtime on Unix systems).
func LoadLocationFromTZData(name string, data []byte) (*Location, error) {
d := dataIO{data, false}
// 4-byte magic "TZif"
if magic := d.read(4); string(magic) != "TZif" {
......@@ -390,7 +391,7 @@ func loadLocation(name string, sources []string) (z *Location, firstErr error) {
for _, source := range sources {
var zoneData, err = loadTzinfo(name, source)
if err == nil {
if z, err = newLocationFromTzinfo(name, zoneData); err == nil {
if z, err = LoadLocationFromTZData(name, zoneData); err == nil {
return z, nil
}
}
......
......@@ -7,6 +7,7 @@ package time_test
import (
"fmt"
"os"
"reflect"
"testing"
"time"
)
......@@ -116,3 +117,27 @@ func TestLocationNames(t *testing.T) {
t.Errorf(`invalid UTC location name: got %q want "UTC"`, time.UTC)
}
}
func TestLoadLocationFromTzinfo(t *testing.T) {
time.ForceZipFileForTesting(true)
defer time.ForceZipFileForTesting(false)
const locationName = "Asia/Jerusalem"
reference, err := time.LoadLocation(locationName)
if err != nil {
t.Fatal(err)
}
tzinfo, err := time.LoadTzinfo(locationName, time.OrigZoneSources[len(time.OrigZoneSources)-1])
if err != nil {
t.Fatal(err)
}
sample, err := time.LoadLocationFromTZData(locationName, tzinfo)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(reference, sample) {
t.Errorf("return values of LoadLocationFromTZData and LoadLocation don't match")
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment