ZhangZhihui's Blog  

 

func main() {
    str := "4:31am +0800 on Oct 1, 2021"
    layout := "3:04pm -0700 on Jan 2, 2006"
    t, err := time.Parse(layout, str)
    if err != nil {
        log.Println("Cannot  parse:", err)
    }
    fmt.Println(t.Format(time.RFC3339))
}

This is the result:

2021-10-01T04:31:00+08:00

Earlier you saw that using the wrong numeral for the layout will result in wrong formatting. This happens in Parse as well, except that this time you will be getting an error. Say you change the layout to this:

layout := "3:09pm -0700 on Jan 2, 2006"

Notice that you changed the layout to :09 instead of :04. You will get this error:

zzh@ZZHPC:~/zd/MyPrograms/Go/study$ go run main.go
2023/10/24 20:15:08 Cannot  parse: parsing time "4:31am +0800 on Oct 1, 2021" as "3:09pm -0700 on Jan 2, 2006": cannot parse "31am +0800 on Oct 1, 2021" as ":09"
0001-01-01T00:00:00Z

If you’re using a time zone abbreviation like SGT or EST, it will still be parsed and it will be considered a location. However, the offset will be zero. Yes, you got that right. It will say what you want it to say but totally ignore your intention of using it as the time zone.

Take a look at what this means. If your value string and layout are like this:

str := "4:31am SGT on Oct 1, 2021" 
layout := "3:04pm MST on Jan 2, 2006"

Print the parsed Time struct instance with a few more layouts from the package:

fmt.Println(t.Format(time.RFC822)) 
fmt.Println(t.Format(time.RFC822Z)) 
fmt.Println(t.Format(time.RFC3339)) 

This is what you get:

zzh@ZZHPC:~/zd/MyPrograms/Go/study$ go run main.go
01 Oct 21 04:31 SGT
01 Oct 21 04:31 +0000
2021-10-01T04:31:00Z

As you can see, the abbreviation is printed nicely, and no error is returned but the offset is obviously wrong since SGT is +0800. In fact, in the RFC 3339 layout shows that it is actually in UTC (it shows a Z).

This is something that can easily trip up someone who is not aware or careless because there is an error returned.

Why is it like this? According to the package documentation:
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. The zone abbreviation “UTC” is recognized as UTC regardless of location. 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.

To solve this problem, you should use a numeric offset like +0800 instead of an abbreviation like SGT.

func main() {
    str := "4:31am +08 on Oct 1, 2021" 
    layout := "3:04pm -07 on Jan 2, 2006"
    t, err := time.Parse(layout, str)
    if err != nil {
        log.Println("Cannot  parse:", err)
    }

    fmt.Println(t.Format(time.RFC822)) 
    fmt.Println(t.Format(time.RFC822Z)) 
    fmt.Println(t.Format(time.RFC3339)) 
}

 

zzh@ZZHPC:/zdata/Github/ztest$ go run main.go
01 Oct 21 04:31 CST
01 Oct 21 04:31 +0800
2021-10-01T04:31:00+08:00

 

posted on 2023-10-06 13:13  ZhangZhihuiAAA  阅读(5)  评论(0编辑  收藏  举报