...

Source file src/time/tzdata/tzdata.go

Documentation: time/tzdata

		 1  // Copyright 2020 The Go Authors. All rights reserved.
		 2  // Use of this source code is governed by a BSD-style
		 3  // license that can be found in the LICENSE file.
		 4  
		 5  //go:generate go run generate_zipdata.go
		 6  
		 7  // Package tzdata provides an embedded copy of the timezone database.
		 8  // If this package is imported anywhere in the program, then if
		 9  // the time package cannot find tzdata files on the system,
		10  // it will use this embedded information.
		11  //
		12  // Importing this package will increase the size of a program by about
		13  // 450 KB.
		14  //
		15  // This package should normally be imported by a program's main package,
		16  // not by a library. Libraries normally shouldn't decide whether to
		17  // include the timezone database in a program.
		18  //
		19  // This package will be automatically imported if you build with
		20  // -tags timetzdata.
		21  package tzdata
		22  
		23  // The test for this package is time/tzdata_test.go.
		24  
		25  import (
		26  	"errors"
		27  	"syscall"
		28  	_ "unsafe" // for go:linkname
		29  )
		30  
		31  // registerLoadFromEmbeddedTZData is defined in package time.
		32  //go:linkname registerLoadFromEmbeddedTZData time.registerLoadFromEmbeddedTZData
		33  func registerLoadFromEmbeddedTZData(func(string) (string, error))
		34  
		35  func init() {
		36  	registerLoadFromEmbeddedTZData(loadFromEmbeddedTZData)
		37  }
		38  
		39  // get4s returns the little-endian 32-bit value at the start of s.
		40  func get4s(s string) int {
		41  	if len(s) < 4 {
		42  		return 0
		43  	}
		44  	return int(s[0]) | int(s[1])<<8 | int(s[2])<<16 | int(s[3])<<24
		45  }
		46  
		47  // get2s returns the little-endian 16-bit value at the start of s.
		48  func get2s(s string) int {
		49  	if len(s) < 2 {
		50  		return 0
		51  	}
		52  	return int(s[0]) | int(s[1])<<8
		53  }
		54  
		55  // loadFromEmbeddedTZData returns the contents of the file with the given
		56  // name in an uncompressed zip file, where the contents of the file can
		57  // be found in embeddedTzdata.
		58  // This is similar to time.loadTzinfoFromZip.
		59  func loadFromEmbeddedTZData(name string) (string, error) {
		60  	const (
		61  		zecheader = 0x06054b50
		62  		zcheader	= 0x02014b50
		63  		ztailsize = 22
		64  
		65  		zheadersize = 30
		66  		zheader		 = 0x04034b50
		67  	)
		68  
		69  	z := zipdata
		70  
		71  	idx := len(z) - ztailsize
		72  	n := get2s(z[idx+10:])
		73  	idx = get4s(z[idx+16:])
		74  
		75  	for i := 0; i < n; i++ {
		76  		// See time.loadTzinfoFromZip for zip entry layout.
		77  		if get4s(z[idx:]) != zcheader {
		78  			break
		79  		}
		80  		meth := get2s(z[idx+10:])
		81  		size := get4s(z[idx+24:])
		82  		namelen := get2s(z[idx+28:])
		83  		xlen := get2s(z[idx+30:])
		84  		fclen := get2s(z[idx+32:])
		85  		off := get4s(z[idx+42:])
		86  		zname := z[idx+46 : idx+46+namelen]
		87  		idx += 46 + namelen + xlen + fclen
		88  		if zname != name {
		89  			continue
		90  		}
		91  		if meth != 0 {
		92  			return "", errors.New("unsupported compression for " + name + " in embedded tzdata")
		93  		}
		94  
		95  		// See time.loadTzinfoFromZip for zip per-file header layout.
		96  		idx = off
		97  		if get4s(z[idx:]) != zheader ||
		98  			get2s(z[idx+8:]) != meth ||
		99  			get2s(z[idx+26:]) != namelen ||
	 100  			z[idx+30:idx+30+namelen] != name {
	 101  			return "", errors.New("corrupt embedded tzdata")
	 102  		}
	 103  		xlen = get2s(z[idx+28:])
	 104  		idx += 30 + namelen + xlen
	 105  		return z[idx : idx+size], nil
	 106  	}
	 107  
	 108  	return "", syscall.ENOENT
	 109  }
	 110  

View as plain text