还记得刚开始看 Go 语言官方 time 标准库文档,翻看时间处理模块的时候,有点摸不着头脑。尤其是时间解析、时间格式化,因为全文比较长,得页面搜索 format 、 parse 之类的关键字查看。但是官方文档只是简单说明根据 Layout 进行解析、格式化,并未说明 Layout 具体怎么作为模板使用。后来查找到此原文的时候,顿觉简洁明了,所以翻译一下并在其基础上补充部分细节,后续也方便自己查阅。此文草稿放在博客里面,真的是拖了好久好久了...

基础示例

Go 语言的时间格式化模板,不像其他很多语言,使用 "yyyy-mm-dd" 类似的格式,而是采用其特殊的模板参数(译者注:事实上,只能使用这个固定的时间作为模板,例如下例及同时间且符合规则的变换格式,使用其他时间来这么写并作为模板是起不到作用的,甚至会报错,这个设计其实有点反直觉):

Mon Jan 2 15:04:05 MST 2006

然后实际的时间,会按照这个格式进行格式化(译者注:这个时间按照中文习惯写成平常的格式更好记一些:“2006-01-02 03:04:05PM -0700”,规律很明显,不过按照西方习惯会变成1234567,读起来更顺。顺道一提, Go 语言发布于 2009)。一个简单的例子如下:

const (
    layoutISO = "2006-01-02"
    layoutUS  = "January 2, 2006"
)
date := "1999-12-31"
t, _ := time.Parse(layoutISO, date)
fmt.Println(t)                  // 1999-12-31 00:00:00 +0000 UTC
fmt.Println(t.Format(layoutUS)) // December 31, 1999

其中两个函数功能:

  • time.Parse 解析日期字符串
  • Format 格式化 time.Time

两个函数签名如下:

func Parse(layout, value string) (Time, error)

func (t Time) Format(layout string) string

时间和日期的常见标准格式

Go 模板参数参数备注
January 2, 2006
01/02/06
Jan-02-06
常见的日期格式
15:04:05
3:04:05 PM
时间格式 24H/12H
Jan _2 15:04:05
Jan _2 15:04:05.000000
日期不带前导0且右对齐的时间戳
(带上微秒)
2006-01-02T15:04:05-0700
2006-01-02
15:04:05
ISO 8601 (RFC 3339)
02 Jan 06 15:04 MST
02 Jan 06 15:04 -0700
RFC 822
(小时数差标识时区)
Mon, 02 Jan 2006 15:04:05 MST
Mon, 02 Jan 2006 15:04:05 -0700
RFC 1123
(小时数差标识时区)

以下 Go 语言 time 库中,预定义的时间戳模板参数常量,也是可以按需使用的:

const (
    ANSIC       = "Mon Jan _2 15:04:05 2006"
    UnixDate    = "Mon Jan _2 15:04:05 MST 2006"
    RubyDate    = "Mon Jan 02 15:04:05 -0700 2006"
    RFC822      = "02 Jan 06 15:04 MST"
    RFC822Z     = "02 Jan 06 15:04 -0700" // RFC822 (小时数差标识时区)
    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 (小时数差标识时区)
    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"
)

可选的 Layout 参数说明

类别参数格式可选项
06  2006
01 1 Jan January
02  2  _2  (带前导0, 不带前导0且左对齐, 不带前导0且右对齐)
星期Mon  Monday
03  3  15 (主要控制是否24H制及是否带前导0)
04  4
05  5
毫秒、微秒、纳秒.000  .000000  .000000000
毫秒、微秒、纳秒.999  .999999  .999999999 ()
am/pmPM  pm
时区MST
时区小时数差-0700  -07  -07:00  Z0700  Z07:00

一些细节

很显然,对于小时格式的配置规则,如果是 24H 制,无法控制有无前导 0 ,配置规则表达能力有限。

只能用 00:00 表示午夜,而不能用 24:00 。但日常采用 07:00 - 24:00 作为时间段的表述很常见。

无法指定包含润秒的时间: 23:59:60 。事实上, time 标准库假定公历不包含润秒。

参考

https://yourbasic.org/golang/format-parse-string-time-date-example/