mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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/68890 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
9a14cd9e75
commit
2951f909ea
5 changed files with 37 additions and 10 deletions
|
|
@ -34,4 +34,5 @@ var (
|
||||||
GetMono = (*Time).mono
|
GetMono = (*Time).mono
|
||||||
ErrLocation = errLocation
|
ErrLocation = errLocation
|
||||||
ReadFile = readFile
|
ReadFile = readFile
|
||||||
|
LoadTzinfo = loadTzinfo
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,11 @@ func initTestingZone() {
|
||||||
localLoc = *z
|
localLoc = *z
|
||||||
}
|
}
|
||||||
|
|
||||||
var origZoneSources = zoneSources
|
var OrigZoneSources = zoneSources
|
||||||
|
|
||||||
func forceZipFileForTesting(zipOnly bool) {
|
func forceZipFileForTesting(zipOnly bool) {
|
||||||
zoneSources = make([]string, len(origZoneSources))
|
zoneSources = make([]string, len(OrigZoneSources))
|
||||||
copy(zoneSources, origZoneSources)
|
copy(zoneSources, OrigZoneSources)
|
||||||
if zipOnly {
|
if zipOnly {
|
||||||
zoneSources = zoneSources[len(zoneSources)-1:]
|
zoneSources = zoneSources[len(zoneSources)-1:]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -294,7 +294,7 @@ func LoadLocation(name string) (*Location, error) {
|
||||||
})
|
})
|
||||||
if *zoneinfo != "" {
|
if *zoneinfo != "" {
|
||||||
if zoneData, err := loadTzinfoFromDirOrZip(*zoneinfo, name); err == nil {
|
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
|
return z, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,11 +79,12 @@ func byteString(p []byte) string {
|
||||||
|
|
||||||
var badData = errors.New("malformed time zone information")
|
var badData = errors.New("malformed time zone information")
|
||||||
|
|
||||||
// newLocationFromTzinfo returns the Location described by Tzinfo with the given name.
|
// LoadLocationFromTZData returns a Location with the given name
|
||||||
// The expected format for Tzinfo is that of a timezone file as they are found in the
|
// initialized from the IANA Time Zone database-formatted data.
|
||||||
// the IANA Time Zone database.
|
// The data should be in the format of a standard IANA time zone file
|
||||||
func newLocationFromTzinfo(name string, Tzinfo []byte) (*Location, error) {
|
// (for example, the content of /etc/localtime on Unix systems).
|
||||||
d := dataIO{Tzinfo, false}
|
func LoadLocationFromTZData(name string, data []byte) (*Location, error) {
|
||||||
|
d := dataIO{data, false}
|
||||||
|
|
||||||
// 4-byte magic "TZif"
|
// 4-byte magic "TZif"
|
||||||
if magic := d.read(4); string(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 {
|
for _, source := range sources {
|
||||||
var zoneData, err = loadTzinfo(name, source)
|
var zoneData, err = loadTzinfo(name, source)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if z, err = newLocationFromTzinfo(name, zoneData); err == nil {
|
if z, err = LoadLocationFromTZData(name, zoneData); err == nil {
|
||||||
return z, nil
|
return z, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ package time_test
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
@ -116,3 +117,27 @@ func TestLocationNames(t *testing.T) {
|
||||||
t.Errorf(`invalid UTC location name: got %q want "UTC"`, time.UTC)
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue