在下面的示例中,无论您为parseAndPrint函数选择的时区,结果始终为“[date] 05:00:00 +0000 UTC”。这段代码有什么问题?时间应根据您选择的时区而变化。 (Go Playground服务器显然是以UTC时区配置的。)
http://play.golang.org/p/wP207BWYEd
package main
import (
"fmt"
"time"
)
func main() {
now := time.Now()
parseAndPrint(now, "BRT")
parseAndPrint(now, "EDT")
parseAndPrint(now, "UTC")
}
func parseAndPrint(now time.Time, timezone string) {
test, err := time.Parse("15:04:05 MST", fmt.Sprintf("05:00:00 %s", timezone))
if err != nil {
fmt.Println(err)
return
}
test = time.Date(
now.Year(),
now.Month(),
now.Day(),
test.Hour(),
test.Minute(),
test.Second(),
test.Nanosecond(),
test.Location(),
)
fmt.Println(test.UTC())
}
答案 0 :(得分:9)
当您解析时间时,您将在当前位置进行解析,只要符合您的预期,就可以了解该时区,并且可以从您所在的位置获知时区缩写。
如果您可以放弃时区,那么您在处理UTC时的所有时间都会更容易规范化。
下一个最简单的方法是使用显式偏移处理所有内容,例如-05:00
。
如果您想处理源自其他时区的时间,则需要使用time.Location
。您可以使用time.LoadLocation
从本地时区数据库加载位置,并使用time.ParseInLocation
解析那里的时间。
答案 1 :(得分:0)
问题:如何使用缩写时区名称(如 UTC
、CET
、BRT
等)正确解析时间?
回答:你最好不要。正如此问题中的 JimB 和其他人 Why doesn't Go's time.Parse() parse the timezone identifier? 仔细建议的那样,您可以预期 Go 仅正确解析两个时区:UTC 和本地时区。
他们没有明确说明的是,您不能指望 Go 使用任何其他时区正确解析时间。至少在我的个人经验中是这样(go1.16.1,Ubuntu 20.04)。
此外,缩写的时区是不明确的。 IST
可能表示印度标准时间、爱尔兰标准时间或以色列标准时间。除非您知道区域位置,否则无法消除歧义,如果您知道位置,则应使用 time.ParseInLocation
。
如果这是用户输入并且您可以控制,您应该更改用户的格式要求以输入具有明确偏移量的时间,因为 JimB 在他们的回答中也提出了建议。确保不要忘记分钟,即使用 -0700
、-07:00
、Z0700
或 Z07:00
但not -07
或Z07
在布局中。并非所有偏移都是整小时。例如,印度标准时间是 UTC+5:30。
如果你别无选择并被迫解析这样的时间,你可以这样做:
func parseTimeWithTimezone(layout, value string) (time.Time, error) {
tt, err := time.Parse(layout, value)
if err != nil {
return time.Time{}, err
}
loc := tt.Location()
zone, offset := tt.Zone()
// Offset will be 0 if timezone is not recognized (or UTC, but that's ok).
// Read carefully https://pkg.go.dev/time#Parse
// In this case we'll try to load location from zone name.
// Timezones that are recognized: local, UTC, GMT, GMT-1, GMT-2, ..., GMT+1, GMT+2, ...
if offset == 0 {
// Make sure you have timezone database available in your system for
// time.LoadLocation to work. Read https://pkg.go.dev/time#LoadLocation
// about where Go looks for timezone database.
// Perhaps the simplest solution is to `import _ "time/tzdata"`, but
// note that it increases binary size by few hundred kilobytes.
// See https://golang.org/doc/go1.15#time/tzdata
loc, err = time.LoadLocation(zone)
if err != nil {
return time.Time{}, err // or `return tt, nil` if you more prefer
// the original Go semantics of returning time with named zone
// but zero offset when timezone is not recognized.
}
}
return time.ParseInLocation(layout, value, loc)
}
请注意,在时区数据库中不作为文件出现的区域名称将无法解析。这些是相当多的。您可以通过检查来查看存在的内容
/usr/share/zoneinfo
、/usr/share/lib/zoneinfo
的内容