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