Files
orbit/internal/timezone/zone.go

62 lines
1.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Package timezone 提供随计划冻结的时区快照,禁止读取宿主机或 ZONEINFO 环境配置。
package timezone
import (
"archive/zip"
"bytes"
_ "embed"
"errors"
"io"
"sync"
"time"
)
// Version 标识 Go 1.27.1 附带的 IANA 快照及文件摘要;升级时须保留旧版本可读能力。
const Version = "go1.27.1-b2d18a7c8fa8"
//go:embed zoneinfo.zip
var data []byte
var zones sync.Map
var archive = sync.OnceValues(func() (*zip.Reader, error) { return zip.NewReader(bytes.NewReader(data), int64(len(data))) })
// Load 仅接受精确的内置名称,返回只读 Location;不接受 Local 或文件系统路径。
func Load(name, version string) (*time.Location, error) {
if version != Version || name == "" || name == "Local" || len(name) > 64 {
return nil, errors.New("unsupported frozen timezone version or name")
}
if name == "UTC" {
return time.UTC, nil
}
if v, ok := zones.Load(name); ok {
return v.(*time.Location), nil
}
a, err := archive()
if err != nil {
return nil, err
}
for _, entry := range a.File {
if entry.Name != name {
continue
}
r, err := entry.Open()
if err != nil {
return nil, err
}
b, err := io.ReadAll(io.LimitReader(r, 1<<20))
closeErr := r.Close()
if err != nil {
return nil, err
}
if closeErr != nil {
return nil, closeErr
}
loc, err := time.LoadLocationFromTZData(name, b)
if err != nil {
return nil, err
}
actual, _ := zones.LoadOrStore(name, loc)
return actual.(*time.Location), nil
}
return nil, errors.New("unknown IANA timezone")
}