【问题标题】:Why does Go time.Format return different value based on timezone?为什么 Go time.Format 会根据时区返回不同的值?
【发布时间】:2021-06-02 14:04:51
【问题描述】:

我认为 Go time.Format 应该根据布局格式化时间。但似乎它会根据时区信息返回不同的值。

package main

import (
    "fmt"
    "time"
)

func main() {

    formats := []string{
        time.RFC3339,
    }
    times := []string{
        "2020-03-08T01:59:50-08:00",
        "2020-03-08T01:59:59-08:00", //daylight saving starts 1 second later
        "2020-03-08T05:59:59-08:00",
    }
    for _, f := range formats {
        for _, t := range times {
            fmt.Printf("Format: %s\n", f)
            t, err := time.Parse(f, t)
            if err != nil {
                panic(err)
            }
            fmt.Printf("unix: %d\n", t.UnixNano())
            fmt.Printf("time: %s\n", t.Format(f))
            t = t.Add(time.Second)
            fmt.Printf("time + 1s: %s\n", t.Format(f))
        }
    }
}

运行输出:

➜ go version
go version go1.15 darwin/amd64
➜ TZ=UTC go run main.go
Format: 2006-01-02T15:04:05Z07:00
unix: 1583661590000000000
time: 2020-03-08T01:59:50-08:00
time + 1s: 2020-03-08T01:59:51-08:00
Format: 2006-01-02T15:04:05Z07:00
unix: 1583661599000000000
time: 2020-03-08T01:59:59-08:00
time + 1s: 2020-03-08T02:00:00-08:00 (a: this is not expected)
unix: 1583675999000000000
time: 2020-03-08T05:59:59-08:00
time + 1s: 2020-03-08T06:00:00-08:00
➜ TZ=America/Los_Angeles go run main.go
Format: 2006-01-02T15:04:05Z07:00
unix: 1583661590000000000
time: 2020-03-08T01:59:50-08:00
time + 1s: 2020-03-08T01:59:51-08:00
Format: 2006-01-02T15:04:05Z07:00 
unix: 1583661599000000000
time: 2020-03-08T01:59:59-08:00
time + 1s: 2020-03-08T03:00:00-07:00 (b: this is expected)
Format: 2006-01-02T15:04:05Z07:00
unix: 1583675999000000000
time: 2020-03-08T05:59:59-08:00
time + 1s: 2020-03-08T06:00:00-08:00 (c: this contradicts with the b)

【问题讨论】:

  • 为什么不期望该值? UTC 没有夏令时,所以格式化的时间是正确的。
  • 再看看这个,我会说2020-03-08T03:00:00-07:00 是结果我没想到...看起来很奇怪我认为可以通过这种方式设置时区。我的意思是,我希望程序解析一个字符串——它没有时区信息,只是一个偏移量!那么为什么要神秘地引入 DST 更改呢?
  • 谢谢大家!更新以包含新时间。还是一头雾水。

标签: go time timezone


【解决方案1】:

该行为已记录在案。 time.Format 的输出只是一个结果,而不是混淆的来源——time.Parse

func Parse:

当解析带有-0700 等区域偏移的时间时,如果偏移 对应于当前位置(Local)使用的时区,则 Parse 在返回的时间内使用该位置和区域。否则它 将时间记录为在一个虚构的位置,时间固定在 给定的区域偏移量。

进一步的解释可以在下面找到 type Location:

Local 表示系统的本地时区。在 Unix 系统上,本地 查阅 TZ 环境变量以查找要使用的时区。不 TZ 表示使用系统默认的 /etc/localtime。 TZ="" 表示使用 UTC。 TZ="foo" 表示使用系统时区目录下的文件 foo。

基本上,go 的解析器尝试从 UTC 偏移量推断时区。如果解析的 UTC 偏移量与TZ 环境变量设置的时区匹配,则在返回的time 中设置该时区。在处理日期和时间方面,简单似乎总是结束。

【讨论】:

    猜你喜欢
    • 2019-12-16
    • 1970-01-01
    • 1970-01-01
    • 2014-02-10
    • 2019-10-25
    • 1970-01-01
    • 1970-01-01
    • 2012-08-12
    • 2017-08-24
    相关资源
    最近更新 更多