Go - Parsing Time Displays Into Structs

发布时间 2023-10-06 13:20:18作者: ZhangZhihuiAAA

 

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:

2021/10/23  20:46:36  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"

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 ))    //  "02  Jan  06  15:04  MST" 
fmt . Println ( t . Format ( time . RFC822Z ))   //  "02  Jan  06  15:04  - 0700" 
fmt . Println ( t . Format ( time . RFC3339 ))   //  "2006 - 01 - 02T15:04:05Z07:00"

This is what you get:

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.
time package documentation
To solve this problem, you should use a numeric offset like +0800 instead of an abbreviation like SGT.