简体   繁体   English

为什么time.Parse没有使用时区?

[英]Why is time.Parse not using the timezone?

Why is time.Parse not using timezone information? 为什么time.Parse不使用时区信息? It should return different time for different timezones. 它应该为不同的时区返回不同的时间。

Code

package main

import (
    "fmt"
    "time"
)

func main() {
    t, err := time.Parse("2006-01-02 MST", "2018-05-11 IST")
    if err != nil {
        return
    }
    t2, err := time.Parse("2006-01-02 MST", "2018-05-11 UTC")
    if err != nil {
        return
    }
    fmt.Println(t.Unix())
    fmt.Println(t2.Unix())
}

Output: 输出:

1525996800
1525996800

Some explanation to the question itself: 对问题本身的一些解释:

These 2 timestamps 2018-05-11 IST and 2018-05-11 UTC do not designate the same time instant because IST has a different offset than UTC: India Standard Time (IST) is 5:30 hours ahead of Coordinated Universal Time (UTC). 这两个时间戳2018-05-11 IST2018-05-11 UTC不指定相同的时间瞬间,因为IST具有与UTC不同的偏移:印度标准时间(IST)比协调世界时(UTC)早5:30 )。

And Time.Unix() returns the elapsed seconds up to the time instant, elapsed since the reference time (January 1, 1970 UTC). 并且Time.Unix()返回自参考时间(1970年1月1日UTC)以来经过的经过的秒数。 Which implies the output should be different! 这意味着输出应该是不同的!

Running your code on the PlayGround indeed gives wrong result ( link ). 在PlayGround上运行代码确实会产生错误的结果( 链接 )。

And it is a timezone related issue. 这是一个与时区相关的问题。 If you try to load the IST timezone: 如果您尝试加载IST时区:

loc, err := time.LoadLocation("IST")
fmt.Println(loc, err)

Output: 输出:

UTC cannot find IST in zip file /usr/local/go/lib/time/zoneinfo.zip

And the reason why "IST" is not supported is because it is ambiguous. 并且不支持“IST”的原因是因为它含糊不清。 It could mean India, Ireland, Israel, etc. time zones, which have different zone offsets and rules. 它可能意味着印度,爱尔兰,以色列等时区,它们具有不同的区域偏移和规则。

And documentation of time.Parse() states that time.Parse()文档说明了这一点

If the zone abbreviation is unknown, Parse records the time as being in a fabricated location with the given zone abbreviation and a zero offset . 如果区域缩写未知,则Parse将时间记录为具有给定区域缩写和零偏移的制造位置。

So the time.time returned by parse.Parse() will have 0 offset just like the UTC zone, hence it will result in the same "unix time" ( Time.Unix() will return the same value). 因此, parse.Parse()返回的time.time将像UTC区域一样具有0偏移量,因此它将导致相同的“unix time”( Time.Unix()将返回相同的值)。

But running it locally (with my CET) timezone gives different, correct result: 但是在本地(使用我的CET)时区运行它会得到不同的正确结果:

t, err := time.Parse("2006-01-02 MST", "2018-05-11 CET")
if err != nil {
    panic(err)
}
t2, err := time.Parse("2006-01-02 MST", "2018-05-11 UTC")
if err != nil {
    panic(err)
}
fmt.Println(t)
fmt.Println(t2)

fmt.Println(t.Unix())
fmt.Println(t2.Unix())

Output: 输出:

2018-05-11 01:00:00 +0200 CEST
2018-05-11 00:00:00 +0000 UTC
1525993200
1525996800

Documentation of time.Parse() has this to say about parsing a time with zone abbreviation: time.Parse()文档说明了使用区域缩写解析时间:

When parsing a time with a zone abbreviation like MST, if the zone abbreviation has a defined offset in the current location, then that offset is used. 在使用区域缩写(如MST)解析时间时,如果区域缩写在当前位置具有已定义的偏移量,则使用该偏移量。 The zone abbreviation "UTC" is recognized as UTC regardless of location. 无论位置如何,区域缩写“UTC”都被识别为UTC。 If the zone abbreviation is unknown, Parse records the time as being in a fabricated location with the given zone abbreviation and a zero offset. 如果区域缩写未知,则Parse将时间记录为具有给定区域缩写和零偏移的制造位置。 This choice means that such a time can be parsed and reformatted with the same layout losslessly, but the exact instant used in the representation will differ by the actual zone offset. 这种选择意味着可以无损地使用相同的布局解析和重新格式化这样的时间,但是表示中使用的确切时刻将因实际的区域偏移而不同。 To avoid such problems, prefer time layouts that use a numeric zone offset, or use ParseInLocation. 要避免此类问题,请首选使用数字区域偏移的时间布局,或使用ParseInLocation。

Documentation suggests to parse with a layout with numeric zone offset, like this: 文档建议使用带有数字区域偏移的布局进行解析,如下所示:

t, err := time.Parse("2006-01-02 -0700", "2018-05-11 +0530")
if err != nil {
    panic(err)
}

Then output (try it on the Go Playground ): 然后输出(在Go Playground上试试):

2018-05-11 00:00:00 +0530 +0530
2018-05-11 00:00:00 +0000 UTC
1525977000
1525996800

Another option is to use time.FixedZone() to construct IST yourself, and use time.ParseInLocation() , passing our manual IST location: 另一种选择是使用time.FixedZone()自己构造IST ,并使用time.ParseInLocation() ,传递我们的手动IST位置:

ist := time.FixedZone("IST", 330*60) // +5:30
t, err := time.ParseInLocation("2006-01-02 MST", "2018-05-11 IST", ist)

Output will be (try it on the Go Playground ): 输出将是(在Go Playground上尝试):

2018-05-11 00:00:00 +0530 IST
2018-05-11 00:00:00 +0000 UTC
1525977000
1525996800

Yet another option is to load Indian IST zone by Kolkata city: 另一种选择是加尔各答市加载印度IST区:

loc, err := time.LoadLocation("Asia/Kolkata")
if err != nil {
    panic(err)
}

Which will produce the same output. 哪个会产生相同的输出。 Try it on the Go Playground . Go Playground尝试一下。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM