IANA时区数据库在大多数操作系统上都可用(*)。Go
标准库也内置了它:
runtime.GOROOT() + "/lib/time/zoneinfo.zip"
操作系统决定时区的选择方式(通过名称)以及该名称是否被记录在任何地方:
ls -al /etc/localtime
/etc/localtime -> /var/db/timezone/zoneinfo/America/New_York
/etc/localtime -> ../usr/share/zoneinfo/America/New_York
在上述情况下,可以推断出名称。
注意:
Go
默认使用本地操作系统时间的
/etc/localtime
(
timezone.go),但是可以通过
TZ
环境变量进行覆盖。
因此,可以通过符号链接目标路径来推断本地操作系统时区的名称。
const localZoneFile = "/etc/localtime"
var ValidateLocationName = true
func LocalTZLocationName() (name string, err error) {
var ok bool
if name, ok = os.LookupEnv("TZ"); ok {
if name == "" {
return "UTC", nil
}
if ValidateLocationName {
_, err = time.LoadLocation(name)
}
return
}
fi, err := os.Lstat(localZoneFile)
if err != nil {
err = fmt.Errorf("failed to stat %q: %w", localZoneFile, err)
return
}
if (fi.Mode() & os.ModeSymlink) == 0 {
err = fmt.Errorf("%q is not a symlink - cannot infer name", localZoneFile)
return
}
p, err := os.Readlink(localZoneFile)
if err != nil {
return
}
name, err = inferFromPath(p)
return
}
func inferFromPath(p string) (name string, err error) {
dir, lname := path.Split(p)
if len(dir) == 0 || len(lname) == 0 {
err = fmt.Errorf("cannot infer timezone name from path: %q", p)
return
}
_, fname := path.Split(dir[:len(dir)-1])
if fname == "zoneinfo" {
name = lname
} else {
name = fname + string(os.PathSeparator) + lname
}
if ValidateLocationName {
_, err = time.LoadLocation(name)
}
return
}
func LocalTZLocationName() (string, error) {
return "", fmt.Errorf("local timezone name inference not available on Windows")
}
(*) 对于Windows
,根据Go源代码(zoneinfo_windows.go),时区信息是从Go标准库加载的,原因是:
// BUG(brainman,rsc): On Windows, the operating system does not provide complete
// time zone information.
// The implementation assumes that this year's rules for daylight savings
// time apply to all previous and future years as well.
Windows注册表键:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation
存储本地时区-但似乎不存储完整的位置名称:
TimeZoneKeyName=Eastern Standard Time
zoneinfo
文件只存储偏移量和简称,例如CEST
,它不包含用户友好的长名称。操作系统通过文件名 路径 加载此信息。路径后缀包含长名称。 - colm.anseo../usr/share/zoneinfo/Europe/Madrid
,这正是我想要的...但我希望用Go语言实现。 - Timo Huovinen