前两天写 go 程序, 用到了time标准库中的ParseInLocation函数, 碰到了一个坑, 记录一下, 免得时间久了忘掉又掉进去.
先来看看标准库中, 对ParseInLocation函数的说明:
ParseInLocation类似Parse但有两个重要的不同之处。第一,当缺少时区信息时,Parse将时间解释为UTC时间,而ParseInLocation将返回值的Location设置为loc;第二,当时间字符串提供了时区偏移量信息时,Parse会尝试去匹配本地时区,而ParseInLocation会去匹配loc。
这个说明, 猛一看好像让人更迷糊了.
再看它提到的Parse函数的说明:
func Parse(layout, value string) (Time, error)
Parse解析一个格式化的时间字符串并返回它代表的时间。
2个联系起来看, 差不多就明白了. 总之, ParseInLocation函数就是 用 layout 参数给出的时间格式 去解析 value 参数给出的时间字符串, 返回一个 Time变量 . error 返回值写go的大家都熟悉不过, loc 参数是给定时区信息.
我的简单代码如下:
timeFormat := "2006-01-02"
st, e := time.ParseInLocation(timeFormat, "2021-05-16", time.Local)
if e != nil {
...
}
注意2点:
- 用 time.Local 传给ParseInLocation的loc参数, 就可以很方便地使用系统本地时区了.
- 第二点也就是我说的 坑 , timeFormat这个时间参数字符串一定要用 2006-01-02 这个日期, 改成2007或改成1月3号都不行, 函数执行就会报错. 对于长时间就用” 2006-01-02 15:04:05 “, 一定要是这个时间, 否则就会解析失败.
实际上, 在time标准库的开头, 给出了下面这样一个const:
const (
ANSIC = "Mon Jan _2 15:04:05 2006"
Unix Date = "Mon Jan _2 15:04:05 MST 2006"
Ruby Date = "Mon Jan 02 15:04:05 -0700 2006"
RFC822 = "02 Jan 06 15:04 MST"
RFC822Z = "02 Jan 06 15:04 -0700" // RFC 822 with numeric zone
RFC850 = "Monday, 02-Jan-06 15:04:05 MST"
RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
RFC1123Z = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone
RFC3339 = "2006-01-02T15:04:05Z07:00"
RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
Kitchen = "3:04PM"
// Handy time stamps.
Stamp = "Jan _2 15:04:05"
StampMilli = "Jan _2 15:04:05.000"
StampMicro = "Jan _2 15:04:05.000000"
StampNano = "Jan _2 15:04:05.000000000"
)
用多种格式表达这个神秘神圣的 2006-01-02 15:04:05 , 为什么要用这个时间? 是否有个来源?
golang 是2009诞生的, 看来不是什么生日梗.
查阅了一番, 觉得下面的说法比较靠谱:
按照format.go源码中的写法:
01/02 03:04:05PM '06 -0700
1月2号下午3点4分5秒, 06年, 时区是-7.
这种写法比较符合m国人的习惯, 他们更方便记忆.
所以golang的设计者, 使用了这个具体的时间来作为格式化字符串, 而抛弃了传统yyyy-MM-dd HH:mm:ss的形式.