mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
Revert "time/tzdata: new package"
This reverts CL 224588. Reason for revert: Test failing on secondary platforms. Change-Id: Ic15fdc73a0d2b860e776733abb82c58809e13160 Reviewed-on: https://go-review.googlesource.com/c/go/+/228200 Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
240eac38e1
commit
5a706d163d
@ -87,20 +87,6 @@ TODO
|
||||
|
||||
<h2 id="library">Core library</h2>
|
||||
|
||||
<h3 id="time/tzdata">New embedded tzdata package</h3>
|
||||
|
||||
<p> <!-- CL 224588 -->
|
||||
Go 1.15 includes a new package,
|
||||
<a href="/pkg/time/tzdata/"><code>time/tzdata</code></a>,
|
||||
that permits embedding the timezone database into a program.
|
||||
Importing this package (as <code>import _ "time/tzdata"</code>)
|
||||
permits the program to find timezone information even if the
|
||||
timezone database is not available on the local system.
|
||||
You can also embed the timezone database by building
|
||||
with <code>-tags timetzdata</code>.
|
||||
Either approach increases the size of the program by about 800K.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
TODO
|
||||
</p>
|
||||
|
@ -28,8 +28,6 @@ rm -f ../../zoneinfo.zip
|
||||
zip -0 -r ../../zoneinfo.zip *
|
||||
cd ../..
|
||||
|
||||
go generate time/tzdata
|
||||
|
||||
echo
|
||||
if [ "$1" = "-work" ]; then
|
||||
echo Left workspace behind in work/.
|
||||
|
@ -166,9 +166,7 @@ var pkgDeps = map[string][]string{
|
||||
"internal/syscall/windows/registry",
|
||||
"syscall",
|
||||
"syscall/js",
|
||||
"time/tzdata",
|
||||
},
|
||||
"time/tzdata": {"L0", "syscall"},
|
||||
|
||||
"internal/cfg": {"L0"},
|
||||
"internal/poll": {"L0", "internal/oserror", "internal/race", "syscall", "time", "unicode/utf16", "unicode/utf8", "internal/syscall/windows", "internal/syscall/unix"},
|
||||
|
@ -1,12 +0,0 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file is used with build tag timetzdata to embed tzdata into
|
||||
// the binary.
|
||||
|
||||
// +build timetzdata
|
||||
|
||||
package time
|
||||
|
||||
import _ "time/tzdata"
|
@ -1,83 +0,0 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// This program generates zipdata.go from $GOROOT/lib/time/zoneinfo.zip.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const header = `// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Code generated by generate_zipdata. DO NOT EDIT.
|
||||
|
||||
// This file contains an embedded zip archive that contains time zone
|
||||
// files compiled using the code and data maintained as part of the
|
||||
// IANA Time Zone Database.
|
||||
// The IANA asserts that the data is in the public domain.
|
||||
|
||||
// For more information, see
|
||||
// https://www.iana.org/time-zones
|
||||
// ftp://ftp.iana.org/tz/code/tz-link.htm
|
||||
// http://tools.ietf.org/html/rfc6557
|
||||
|
||||
package tzdata
|
||||
|
||||
const zipdata = `
|
||||
|
||||
func main() {
|
||||
// We should be run in the $GOROOT/src/time/tzdata directory.
|
||||
data, err := ioutil.ReadFile("../../../lib/time/zoneinfo.zip")
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
// For convenience try $GOROOT as a backup.
|
||||
data, err = ioutil.ReadFile(filepath.Join(runtime.GOROOT(), "lib", "time", "zoneinfo.zip"))
|
||||
}
|
||||
if err != nil {
|
||||
die("cannot find zoneinfo.zip file: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
of, err := os.Create("zipdata.go")
|
||||
if err != nil {
|
||||
die("%v", err)
|
||||
}
|
||||
|
||||
buf := bufio.NewWriter(of)
|
||||
buf.WriteString(header)
|
||||
|
||||
ds := string(data)
|
||||
i := 0
|
||||
const chunk = 60
|
||||
for ; i+chunk < len(data); i += chunk {
|
||||
if i > 0 {
|
||||
buf.WriteRune('\t')
|
||||
}
|
||||
fmt.Fprintf(buf, "%s +\n", strconv.Quote(ds[i:i+chunk]))
|
||||
}
|
||||
fmt.Fprintf(buf, "\t%s\n", strconv.Quote(ds[i:]))
|
||||
|
||||
if err := buf.Flush(); err != nil {
|
||||
die("error writing to zipdata.go: %v", err)
|
||||
}
|
||||
if err := of.Close(); err != nil {
|
||||
die("error closing zipdata.go: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func die(format string, args ...interface{}) {
|
||||
fmt.Fprintf(os.Stderr, format+"\n", args...)
|
||||
os.Exit(1)
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate go run generate_zipdata.go
|
||||
|
||||
// Package tzdata provides an embedded copy of the timezone database.
|
||||
// If this package is imported anywhere in the program, then if
|
||||
// the time package cannot find tzdata files on the system,
|
||||
// it will use this embedded information.
|
||||
//
|
||||
// Importing this package will increase the size of a program by about
|
||||
// 800K.
|
||||
//
|
||||
// This package should normally be imported by a program's main package,
|
||||
// not by a library. Libraries normally shouldn't decide whether to
|
||||
// include the timezone database in a program.
|
||||
//
|
||||
// This package will be automatically imported if you build with
|
||||
// -tags timetzdata.
|
||||
package tzdata
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"syscall"
|
||||
_ "unsafe" // for go:linkname
|
||||
)
|
||||
|
||||
// registerLoadFromEmbeddedTZData is defined in package time.
|
||||
//go:linkname registerLoadFromEmbeddedTZData time.registerLoadFromEmbeddedTZData
|
||||
func registerLoadFromEmbeddedTZData(func(string) (string, error))
|
||||
|
||||
func init() {
|
||||
registerLoadFromEmbeddedTZData(loadFromEmbeddedTZData)
|
||||
}
|
||||
|
||||
// get4s returns the little-endian 32-bit value at the start of s.
|
||||
func get4s(s string) int {
|
||||
if len(s) < 4 {
|
||||
return 0
|
||||
}
|
||||
return int(s[0]) | int(s[1])<<8 | int(s[2])<<16 | int(s[3])<<24
|
||||
}
|
||||
|
||||
// get2s returns the little-endian 16-bit value at the start of s.
|
||||
func get2s(s string) int {
|
||||
if len(s) < 2 {
|
||||
return 0
|
||||
}
|
||||
return int(s[0]) | int(s[1])<<8
|
||||
}
|
||||
|
||||
// loadFromEmbeddedTZData returns the contents of the file with the given
|
||||
// name in an uncompressed zip file, where the contents of the file can
|
||||
// be found in embeddedTzdata.
|
||||
// This is similar to time.loadTzinfoFromZip.
|
||||
func loadFromEmbeddedTZData(name string) (string, error) {
|
||||
const (
|
||||
zecheader = 0x06054b50
|
||||
zcheader = 0x02014b50
|
||||
ztailsize = 22
|
||||
|
||||
zheadersize = 30
|
||||
zheader = 0x04034b50
|
||||
)
|
||||
|
||||
z := zipdata
|
||||
|
||||
idx := len(z) - ztailsize
|
||||
n := get2s(z[idx+10:])
|
||||
idx = get4s(z[idx+16:])
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
// See time.loadTzinfoFromZip for zip entry layout.
|
||||
if get4s(z[idx:]) != zcheader {
|
||||
break
|
||||
}
|
||||
meth := get2s(z[idx+10:])
|
||||
size := get4s(z[idx+24:])
|
||||
namelen := get2s(z[idx+28:])
|
||||
xlen := get2s(z[idx+30:])
|
||||
fclen := get2s(z[idx+32:])
|
||||
off := get4s(z[idx+42:])
|
||||
zname := z[idx+46 : idx+46+namelen]
|
||||
idx += 46 + namelen + xlen + fclen
|
||||
if zname != name {
|
||||
continue
|
||||
}
|
||||
if meth != 0 {
|
||||
return "", errors.New("unsupported compression for " + name + " in embedded tzdata")
|
||||
}
|
||||
|
||||
// See time.loadTzinfoFromZip for zip per-file header layout.
|
||||
idx = off
|
||||
if get4s(z[idx:]) != zheader ||
|
||||
get2s(z[idx+8:]) != meth ||
|
||||
get2s(z[idx+26:]) != namelen ||
|
||||
z[idx+30:idx+30+namelen] != name {
|
||||
return "", errors.New("corrupt embedded tzdata")
|
||||
}
|
||||
xlen = get2s(z[idx+28:])
|
||||
idx += 30 + namelen + xlen
|
||||
return z[idx : idx+size], nil
|
||||
}
|
||||
|
||||
return "", syscall.ENOENT
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package tzdata
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var zones = []string{
|
||||
"Asia/Jerusalem",
|
||||
"America/Los_Angeles",
|
||||
}
|
||||
|
||||
func TestEmbeddedTZData(t *testing.T) {
|
||||
for _, zone := range zones {
|
||||
ref, err := time.LoadLocation(zone)
|
||||
if err != nil {
|
||||
t.Errorf("LoadLocation(%q): %v", zone, err)
|
||||
continue
|
||||
}
|
||||
|
||||
embedded, err := loadFromEmbeddedTZData(zone)
|
||||
if err != nil {
|
||||
t.Errorf("loadFromEmbeddedTZData(%q): %v", zone, err)
|
||||
continue
|
||||
}
|
||||
sample, err := time.LoadLocationFromTZData(zone, []byte(embedded))
|
||||
if err != nil {
|
||||
t.Errorf("LoadLocationFromTZData failed for %q: %v", zone, err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Compare the name and zone fields of ref and sample.
|
||||
// The tx field changes faster as tzdata is updated.
|
||||
// The cache fields are expected to differ.
|
||||
v1 := reflect.ValueOf(ref).Elem()
|
||||
v2 := reflect.ValueOf(sample).Elem()
|
||||
typ := v1.Type()
|
||||
nf := typ.NumField()
|
||||
found := 0
|
||||
for i := 0; i < nf; i++ {
|
||||
ft := typ.Field(i)
|
||||
if ft.Name != "name" && ft.Name != "zone" {
|
||||
continue
|
||||
}
|
||||
found++
|
||||
if !equal(t, v1.Field(i), v2.Field(i)) {
|
||||
t.Errorf("zone %s: system and embedded tzdata field %s differs", zone, ft.Name)
|
||||
}
|
||||
}
|
||||
if found != 2 {
|
||||
t.Errorf("test must be updated for change to time.Location struct")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// equal is a small version of reflect.DeepEqual that we use to
|
||||
// compare the values of zoneinfo unexported fields.
|
||||
func equal(t *testing.T, f1, f2 reflect.Value) bool {
|
||||
switch f1.Type().Kind() {
|
||||
case reflect.Slice:
|
||||
if f1.Len() != f2.Len() {
|
||||
return false
|
||||
}
|
||||
for i := 0; i < f1.Len(); i++ {
|
||||
if !equal(t, f1.Index(i), f2.Index(i)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
case reflect.Struct:
|
||||
nf := f1.Type().NumField()
|
||||
for i := 0; i < nf; i++ {
|
||||
if !equal(t, f1.Field(i), f2.Field(i)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
case reflect.String:
|
||||
return f1.String() == f2.String()
|
||||
case reflect.Bool:
|
||||
return f1.Bool() == f2.Bool()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return f1.Int() == f2.Int()
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return f1.Uint() == f2.Uint()
|
||||
default:
|
||||
t.Errorf("test internal error: unsupported kind %v", f1.Type().Kind())
|
||||
return true
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -15,18 +15,6 @@ import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// registerLoadFromEmbeddedTZData is called by the time/tzdata package,
|
||||
// if it is imported.
|
||||
func registerLoadFromEmbeddedTZData(f func(string) (string, error)) {
|
||||
loadFromEmbeddedTZData = f
|
||||
}
|
||||
|
||||
// loadFromEmbeddedTZData is used to load a specific tzdata file
|
||||
// from tzdata information embedded in the binary itself.
|
||||
// This is set when the time/tzdata package is imported,
|
||||
// via registerLoadFromEmbeddedTzdata.
|
||||
var loadFromEmbeddedTZData func(zipname string) (string, error)
|
||||
|
||||
// maxFileSize is the max permitted size of files read by readFile.
|
||||
// As reference, the zoneinfo.zip distributed by Go is ~350 KB,
|
||||
// so 10MB is overkill.
|
||||
@ -498,17 +486,6 @@ func loadLocation(name string, sources []string) (z *Location, firstErr error) {
|
||||
firstErr = err
|
||||
}
|
||||
}
|
||||
if loadFromEmbeddedTZData != nil {
|
||||
zonedata, err := loadFromEmbeddedTZData(name)
|
||||
if err == nil {
|
||||
if z, err = LoadLocationFromTZData(name, []byte(zonedata)); err == nil {
|
||||
return z, nil
|
||||
}
|
||||
}
|
||||
if firstErr == nil && err != syscall.ENOENT {
|
||||
firstErr = err
|
||||
}
|
||||
}
|
||||
if firstErr != nil {
|
||||
return nil, firstErr
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user