先来看一个简单的例子:
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println(time.Now().Format("2006"))
}
我们会觉得这会输出什么呢?输出的是 2022
,也就是当前年份。
另一个例子:
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println(time.Now().Format("2006-01-02 15:04:05"))
}
输出:2022-08-04 09:43:56
如果之前写其他语言的,看到这个结果估计和我一样觉得百思不得其解,为什么不是 Y-m-d H:i:s
这种格式呢?而且那个参数看起来就是一个时间戳。
答案我们可以点开 Format
的源码看看就知道了:
func (t Time) Format(layout string) string {
// ... 省略,下面这个调用才是关键
b = t.AppendFormat(b, layout)
// ... 省略
}
我们看到 Format
里面具体处理逻辑在 AppendFormat
函数里面,再点开 AppendFormat
看看:
switch std & stdMask {
case stdYear:
y := year
if y < 0 {
y = -y
}
b = appendInt(b, y%100, 2)
case stdLongYear:
b = appendInt(b, year, 4)
case stdMonth:
b = append(b, month.String()[:3]...)
case stdLongMonth:
m := month.String()
b = append(b, m...)
// ... 省略其他 case
}
我们可以看到里面的 stdYear
、stdLongYear
之类的常量实际上就是我们传入到 Format
的参数里面的数字。
const (
_ = iota
stdLongMonth = iota + stdNeedDate // "January"
stdMonth // "Jan"
stdNumMonth // "1"
stdZeroMonth // "01"
stdLongWeekDay // "Monday"
stdWeekDay // "Mon"
stdDay // "2"
stdUnderDay // "_2"
stdZeroDay // "02"
stdUnderYearDay // "__2"
stdZeroYearDay // "002"
stdHour = iota + stdNeedClock // "15"
stdHour12 // "3"
stdZeroHour12 // "03"
stdMinute // "4"
stdZeroMinute // "04"
stdSecond // "5"
stdZeroSecond // "05"
stdLongYear = iota + stdNeedDate // "2006"
stdYear // "06"
stdPM = iota + stdNeedClock // "PM"
stdpm // "pm"
stdTZ = iota // "MST"
stdISO8601TZ // "Z0700" // prints Z for UTC
stdISO8601SecondsTZ // "Z070000"
stdISO8601ShortTZ // "Z07"
stdISO8601ColonTZ // "Z07:00" // prints Z for UTC
stdISO8601ColonSecondsTZ // "Z07:00:00"
stdNumTZ // "-0700" // always numeric
stdNumSecondsTz // "-070000"
stdNumShortTZ // "-07" // always numeric
stdNumColonTZ // "-07:00" // always numeric
stdNumColonSecondsTZ // "-07:00:00"
stdFracSecond0 // ".0", ".00", ... , trailing zeros included
stdFracSecond9 // ".9", ".99", ..., trailing zeros omitted
stdNeedDate = 1 << 8 // need month, day, year
stdNeedClock = 2 << 8 // need hour, minute, second
stdArgShift = 16 // extra argument in high bits, above low stdArgShift
stdSeparatorShift = 28 // extra argument in high 4 bits for fractional second separators
stdMask = 1<<stdArgShift - 1 // mask out argument
)
所以,其实答案已经有了,我们对照一下我们的参数 2006-01-02 15:04:05
,可以很简单在上述常量里面找到对应的常量:
2006
=> stdLongYear
01
=> stdZeroMonth
02
=> stdZeroDay
15
=> stdHour
04
=> stdZeroMinute
05
=> stdZeroSecond
而 layout
参数里面的 -
以及 :
都会原样输出。
根据给出的这些常量,我们就可以将时间格式化为我们想要的格式了。