如何解析2015年10月5日星期一00:24:08 +0800(GMT + 08: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"

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)

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"