如何解析 Mon, 5 Oct 2015 00:24:08 +0800 (GMT+08:00) 这个日期时间字符串?

huangapple go评论97阅读模式
英文:

How to parse Mon, 5 Oct 2015 00:24:08 +0800 (GMT+08:00)

问题

我正在尝试解析一个时间值(通过电子邮件接收),但我找不到应该使用的布局。

package main

import "fmt"
import "time"

func main() {
    layout := "Mon, _2 Jan 2006 15:04:05 -0700 (MST-07:00)"
    data := "Mon, 5 Oct 2015 00:24:08 +0800 (GMT+08:00)"
    t, err := time.Parse(layout, data)
    if err != nil {
        panic(err)
    }
    fmt.Println(t)
}

查看

panic: parsing time "Mon, 5 Oct 2015 00:24:08 +0800 (GMT+08:00)" as "Mon, _2 Jan 2006 15:04:05 -0700 (MST-07:00)": cannot parse ":00)" as "-07:00"
英文:

I'm trying to parse a time value (received via email) but I can't find what layout I should use.

package main

import "fmt"
import "time"

func main() {
	layout := "Mon, _2 Jan 2006 15:04:05 -0700 (MST-07:00)"
	data := "Mon, 5 Oct 2015 00:24:08 +0800 (GMT+08:00)"
	t, err := time.Parse(layout, data)
	if err != nil {
		panic(err)
	}
	fmt.Println(t)
}

Check

panic: parsing time "Mon, 5 Oct 2015 00:24:08 +0800 (GMT+08:00)" as "Mon, _2 Jan 2006 15:04:05 -0700 (MST-07:00)": cannot parse ":00)" as "-07:00"

答案1

得分: 5

请阅读**重要提示!**部分,以获得完整的图片,因为最后一部分包括GMT并不是它看起来的样子(也就是说,它不是时区缩写)。


你输入的时间字符串无法直接使用time包进行解析,因为在最后一部分的(GMT+08:00)中,时区缩写和时区偏移没有用任何额外字符分隔开。由于时区缩写不限于3个字符,"+08"也被视为时区缩写的一部分,这将只剩下":00)"与时区偏移"-07:00"匹配,因此会出现错误消息:

无法将":00)"解析为"-07:00"

可能的解决方法:

简单地去掉多余的时区偏移,因为它是多余的(重复出现,因为时区偏移已经包含了两次):

func Parse(s string) (time.Time, error) {
	if len(s) < 7 {
		return time.Time{}, errors.New("太短了!")
	}
	s = s[:len(s)-7]
	layout := "Mon, _2 Jan 2006 15:04:05 -0700 (MST"
	return time.Parse(layout, s)
}

并使用它:

data := "Mon, 5 Oct 2015 00:24:08 +0800 (GMT+08:00)"
t, err := Parse(data)
if err != nil {
	panic(err)
}
fmt.Println(t)

Go Playground上尝试一下。

重要提示!

尽管在逻辑上分析你的输入时间字符串:

Mon, 5 Oct 2015 00:24:08 +0800 (GMT+08:00)

最后一部分"(GMT+08:00)"并不表示时区缩写(GMT不是+0800而是+0000)!它只是一个辅助文本,向读者解释+0800是要添加到GMT时区的一个时区偏移量,因此很可能它总是GMT,但不是因为时间是在GMT时区指定的,而是因为它解释了时区偏移量表示要添加到GMT时间的偏移量。因此,它不是时间规范的一部分,不应该被解析。

因此,只需去掉最后的所有部分,并像这样解析它:

func Parse(s string) (time.Time, error) {
	if len(s) < 12 {
		return time.Time{}, errors.New("太短了!")
	}
	s = s[:len(s)-12]
	layout := "Mon, 2 Jan 2006 15:04:05 -0700"
	return time.Parse(layout, s)
}

还要注意,如果这确实是情况(它不是时区缩写,而总是"GMT"),你可以在不截断输入字符串的情况下解析它,只需将布局更改为包含静态文本"GMT"而不是时区缩写指示符"MST"

layout := "Mon, 2 Jan 2006 15:04:05 -0700 (GMT-07:00)"
data := "Mon, 5 Oct 2015 00:24:08 +0800 (GMT+08:00)"
t, err := time.Parse(layout, data)
英文:

Please read the Important note! section to get a full picture as the last part including GMT is not what it seems (that is, it is not the zone abbreviation).


Your input time string is not parsable as-is with the time package because in the last part (GMT+08:00) the zone abbreviation and the zone offset are not separated with any extra characters. And since the zone abbreviation is not limited to 3 characters, the "+08" is also treated as part of the zone abbreviation, which will only leave the rest ":00)" to match the zone offset "-07:00" hence the error message:

cannot parse ":00)" as "-07:00"

Possible workaround:

Simply cut off the extra zone offset as it is redundant (duplicate because zone offset is included twice):

func Parse(s string) (time.Time, error) {
	if len(s) < 7 {
		return time.Time{}, errors.New("Too short!")
	}
	s = s[:len(s)-7]
	layout := "Mon, _2 Jan 2006 15:04:05 -0700 (MST"
	return time.Parse(layout, s)
}

And using it:

data := "Mon, 5 Oct 2015 00:24:08 +0800 (GMT+08:00)"
t, err := Parse(data)
if err != nil {
	panic(err)
}
fmt.Println(t)

Try it on the Go Playground.

Important note!

Although logically analyzing your input time string:

Mon, 5 Oct 2015 00:24:08 +0800 (GMT+08:00)

The last part "(GMT+08:00)" does not denote the zone abbreviation (GMT is not +0800 but +0000)! It is just a helper text to the reader explaining that the +0800 is a zone offset to be added to the GMT timezone, so most likely it will always be GMT but not because the time is specified in the GMT timezone but because it explains that the zone offset means an offset to be added to the GMT time. And as such, it is not part of the time specification and should not be parsed.

So instead cut off all the last part and parse it like this:

func Parse(s string) (time.Time, error) {
	if len(s) < 12 {
		return time.Time{}, errors.New("Too short!")
	}
	s = s[:len(s)-12]
	layout := "Mon, 2 Jan 2006 15:04:05 -0700"
	return time.Parse(layout, s)
}

Also note that if this is really the case (that it is not the zone abbreviation but it will always be "GMT"), you can parse the input string without truncating it by changing your layout to include the static text "GMT" instead of the zone abbreviation specifier "MST":

layout := "Mon, 2 Jan 2006 15:04:05 -0700 (GMT-07:00)"
data := "Mon, 5 Oct 2015 00:24:08 +0800 (GMT+08:00)"
t, err := time.Parse(layout, data)

答案2

得分: -1

在MST和-之间加一个空格可以解决这个错误。

layout := "Mon, _2 Jan 2006 15:04:05 -0700 (MST -07:00)"
data := "Mon, 5 Oct 2015 00:24:08 +0800 (GMT +08:00)"

这样可以工作,但并不能真正解决你的问题。

为什么不去掉多余的时区部分呢?你已经定义了+0800。

layout := "Mon, _2 Jan 2006 15:04:05 -0700"
data := "Mon, 5 Oct 2015 00:24:08 +0800"

英文:

Having a space between MST and - solves the panic.

layout := "Mon, _2 Jan 2006 15:04:05 -0700 (MST -07:00)"
data := "Mon, 5 Oct 2015 00:24:08 +0800 (GMT +08:00)"

This works, however it does not really solve your problem.

Why not trimming the redundant timezone part? You already have +0800 defined.

layout := "Mon, _2 Jan 2006 15:04:05 -0700"
data := "Mon, 5 Oct 2015 00:24:08 +0800"

huangapple
  • 本文由 发表于 2015年10月5日 15:34:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/32943398.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定