1
0
mirror of https://github.com/golang/go synced 2024-07-03 08:51:14 +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:
Ian Lance Taylor 2020-04-13 23:26:39 +00:00
parent 240eac38e1
commit 5a706d163d
9 changed files with 0 additions and 13386 deletions

View File

@ -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>

View File

@ -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/.

View File

@ -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"},

View File

@ -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"

View File

@ -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)
}

View File

@ -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
}

View File

@ -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

View File

@ -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
}