Go的time.Parse()为什么不解析时区标识符? [英] Why doesn't Go's time.Parse() parse the timezone identifier?

查看:36
本文介绍了Go的time.Parse()为什么不解析时区标识符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下代码:

package main

import (
    "time"
    "fmt"
)

const (
    format = "2006 01 02 15:04 MST"

    date = "2018 08 01 12:00 EDT"
)

func main() {
    aloc, _ := time.LoadLocation("America/New_York")
    eloc, _ := time.LoadLocation("Europe/Berlin")
    tn, _ := time.Parse(format, date)
    tl, _ := time.ParseInLocation(format, date, aloc)

    fmt.Println(tn) // Says +0000 despite EDT being -0400
    fmt.Println(tn.In(eloc)) // Expect 18:00, but get 14:00
    fmt.Println(tl) // Correctly -0400
    fmt.Println(tl.In(eloc)) // Correctly 18:00
}

您也可以在去游乐场上试用.

运行它时,我得到了这个结果(在我自己的系统上和通过Playground):

When I run it, I get this result (both on my own system and through the Playground):

2018-08-01 12:00:00 +0000 EDT
2018-08-01 14:00:00 +0200 CEST
2018-08-01 12:00:00 -0400 EDT
2018-08-01 18:00:00 +0200 CEST

我曾期望第一行和第三行是相同的,第二行和第四行是相同的.

I had expected the first and third line to be the same, and the second and fourth to be the same.

在我看来,Go的时区库无法解析我在日期字符串中编写的"EDT"时区标识符,尽管它是格式的一部分.

It seems to me that Go's time library doesn't parse the "EDT" timezone identifier I've written in the date string, despite it being part of the format.

我自己的系统(Fedora 26)也将EST/EDT识别为时区:

My own system (Fedora 26) also recognises EST/EDT as a timezone:

$ TZ='America/New_York' date 080112002018
Wed  1 Aug 12:00:00 EDT 2018

当然,如您所见,我可以通过使用 ParseInLocation()来强制解决此问题,但这仅在我事先知道时区 时才有用.否则,我需要自己将日期字符串的"EDT"部分解析为"America/New_York".

Of course, as you can see, I can force the issue by using ParseInLocation(), but that's only useful if I know the timezone beforehand. Otherwise I need to parse the 'EDT' part of the date string into 'America/New_York' myself.

或者我想念什么吗?

推荐答案

time#Parse 引用:

当使用诸如 MST 之类的区域缩写解析时间时,如果该区域缩写在当前位置有一个已定义的偏移量,然后该偏移量使用.

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.

此处的键是当前位置".对我来说,就是 CST .使用此作为预期:

The key here is "current location". For me, that is CST. Using this works as expected:

package main

import (
   "log"
   "time"
)

func main() {
   t, e := time.Parse(time.RFC1123, "Wed, 01 Aug 2018 12:00:00 CST")
   if e != nil {
      log.Fatal(e)
   }
   s := t.String()
   println(s == "2018-08-01 13:00:00 -0500 CDT")
}

如果区域缩写未知,则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.

package main

import (
   "log"
   "time"
)

func main() {
   t, e := time.Parse(time.RFC1123, "Wed, 01 Aug 2018 12:00:00 EDT")
   if e != nil {
      log.Fatal(e)
   }
   s := t.String()
   println(s == "2018-08-01 12:00:00 +0000 EDT")
}

为避免此类问题,请首选使用数字区域偏移量的时间布局,或使用ParseInLocation.

To avoid such problems, prefer time layouts that use a numeric zone offset, or use ParseInLocation.

package main

import (
   "log"
   "time"
)

func check(e error) {
   if e != nil {
      log.Fatal(e)
   }
}

func main() {
   // example 1
   t1, e := time.Parse(time.RFC1123Z, "Wed, 01 Aug 2018 12:00:00 -0400")
   check(e)
   s1 := t1.String()
   // example 2
   loc, e := time.LoadLocation("America/New_York")
   check(e)
   t2, e := time.ParseInLocation(time.RFC1123, "Wed, 01 Aug 2018 12:00:00 EDT", loc)
   check(e)
   s2 := t2.String()
   // print
   println(s1 == "2018-08-01 12:00:00 -0400 -0400", s2 == "2018-08-01 12:00:00 -0400 EDT")
}

这篇关于Go的time.Parse()为什么不解析时区标识符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆