如何正确解析时区代码

时间:2014-08-18 17:02:18

标签: parsing time go timezone

在下面的示例中,无论您为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())
}

2 个答案:

答案 0 :(得分:9)

当您解析时间时,您将在当前位置进行解析,只要符合您的预期,就可以了解该时区,并且可以从您所在的位置获知时区缩写。

如果您可以放弃时区,那么您在处理UTC时的所有时间都会更容易规范化。

下一个最简单的方法是使用显式偏移处理所有内容,例如-05:00

如果您想处理源自其他时区的时间,则需要使用time.Location。您可以使用time.LoadLocation从本地时区数据库加载位置,并使用time.ParseInLocation解析那里的时间。

答案 1 :(得分:0)

问题:如何使用缩写时区名称(如 UTCCETBRT 等)正确解析时间?

回答:你最好不要。正如此问题中的 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:00Z0700Z07:00not -07Z07 在布局中。并非所有偏移都是整小时。例如,印度标准时间是 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)
}

请注意,在时区数据库中不作为文件出现的区域名称将无法解析。这些是相当多的。您可以通过检查来查看存在的内容