time包提供了时间的显示和测量用的函数。日历的计算采用的是公历。
https://pkg.go.dev/time
1、时间中的类型
1.1、时间
time.Time 类型表示时间。我们可以通过 time.Now()
函数获取当前的时间对象,然后获取时间对象的年月日时分秒等信息。示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
| func timeDemo() { now := time.Now() fmt.Printf("current time:%v\n", now)
year := now.Year() month := now.Month() day := now.Day() hour := now.Hour() minute := now.Minute() second := now.Second() fmt.Printf("%d-%02d-%02d %02d:%02d:%02d\n", year, month, day, hour, minute, second) }
|
1.2、时间戳
时间戳是自1970年1月1日(08:00:00GMT)至当前时间的总毫秒数。它也被称为Unix时间戳(UnixTimestamp)。
基于时间对象获取时间戳的示例代码如下:
1 2 3 4 5 6 7
| func timestampDemo() { now := time.Now() timestamp1 := now.Unix() timestamp2 := now.UnixNano() fmt.Printf("current timestamp1:%v\n", timestamp1) fmt.Printf("current timestamp2:%v\n", timestamp2) }
|
使用 time.Unix()
函数可以将时间戳转为时间格式。
1 2 3 4 5 6 7 8 9 10 11
| func timestampDemo2(timestamp int64) { timeObj := time.Unix(timestamp, 0) fmt.Println(timeObj) year := timeObj.Year() month := timeObj.Month() day := timeObj.Day() hour := timeObj.Hour() minute := timeObj.Minute() second := timeObj.Second() fmt.Printf("%d-%02d-%02d %02d:%02d:%02d\n", year, month, day, hour, minute, second) }
|
1.3、时间间隔
time.Duration 是 time 包定义的一个类型,它代表两个时间点之间经过的时间,以纳秒为单位。time.Duration 表示一段时间间隔,可表示的最长时间段大约290年。
time 包中定义的时间间隔类型的常量如下:
1 2 3 4 5 6 7 8
| const ( Nanosecond Duration = 1 Microsecond = 1000 * Nanosecond Millisecond = 1000 * Microsecond Second = 1000 * Millisecond Minute = 60 * Second Hour = 60 * Minute )
|
例如:time.Duration
表示 1 纳秒,time.Second
表示 1 秒。
2、创建时间
1 2 3 4 5 6 7 8
| nowTime := time.Now() fmt.Printf("当前时间为:%T\n", nowTime) fmt.Println(nowTime)
customTime := time.Date(2008, 7, 15, 13, 30,0,0, time.Local) fmt.Println(customTime)
|
4、时间操作
Add 求时间点t+d。
我们在日常的编码过程中可能会遇到要求时间+时间间隔的需求,Go语言的时间对象有提供Add方法如下:
1
| func (t Time) Add(d Duration) Time
|
举个例子,求一个小时之后的时间:
1 2 3 4 5
| func main() { now := time.Now() later := now.Add(time.Hour) fmt.Println(later) }
|
Sub 求两个时间之间的差值
1
| func (t Time) Sub(u Time) Duration
|
返回一个时间段t-u。如果结果超出了Duration可以表示的最大值/最小值,将返回最大值/最小值。要获取时间点t-d(d为Duration),可以使用t.Add(-d)。
1 2 3 4 5 6
| func main() { now := time.Now() later := now.Add(time.Hour) ret := later.Sub(now) fmt.Println(ret) }
|
Equal 判断两个时间是否相同
1
| func (t Time) Equal(u Time) bool
|
判断两个时间是否相同,会考虑时区的影响,因此不同时区标准的时间也可以正确比较。本方法和用t==u不同,这种方法还会比较地点和时区信息。
Before
1
| func (t Time) Before(u Time) bool
|
如果t代表的时间点在u之前,返回真;否则返回假。
After
1
| func (t Time) After(u Time) bool
|
如果t代表的时间点在u之后,返回真;否则返回假。
Sleep
1
| time.Sleep(time.Second * 3)
|
5、定时器
使用time.Tick(时间间隔)来设置定时器,定时器的本质上是一个通道(channel)。
1 2 3 4 5 6
| func tickDemo() { ticker := time.Tick(time.Second) for i := range ticker { fmt.Println(i) } }
|
1 2 3
| time.AfterFunc(time.Second*10, func() { fmt.Println("10秒后执行") })
|
时间中的通道操作(定时器)
标准库中的Timer可以让用户自定义一个定时器,在对用select处理多个channel的超时、单channel读写的超时等情形时很方便:
1 2 3
| timer := time.NewTimer(time.Second * 3) ch := timer.C fmt.Println(<-ch)
|
配合协程:
1 2 3 4 5 6 7 8 9
| timer := time.NewTimer(time.Second * 3) go func() { <- timer.C fmt.Println("timer 结束") }()
time.Sleep(time.Second * 5) flag := timer.Stop() fmt.Println(flag)
|
time.After函数的使用:
1 2 3
| ch := time.After(time.Second * 3) newTime := <-ch fmt.Println(newTime)
|
6、时间格式化和解析
需要注意的是 Go 中格式化时间模板不是常见的 Y-m-d H:M:S
而是使用 Go 的诞生时间2006年1月2号15点04分(记忆口诀为2006 1 2 3 4)。也许这就是技术人员的浪漫吧。
补充:如果想格式化为12小时方式,需指定PM。
1 2 3 4 5 6 7 8 9 10 11
| func formatDemo() { now := time.Now() fmt.Println(now.Format("2006-01-02 15:04:05.000 Mon Jan")) fmt.Println(now.Format("2006-01-02 03:04:05.000 PM Mon Jan")) fmt.Println(now.Format("2006/01/02 15:04")) fmt.Println(now.Format("15:04 2006/01/02")) fmt.Println(now.Format("2006/01/02")) }
|
解析字符串格式的时间 parse
1
| func Parse(layout, value string) (Time, error)
|
解析一个格式化的时间字符串并返回它代表的时间,如果缺少表示时区的信息,Parse会将时区设置为UTC。
1
| func ParseInLocation(layout, value string, loc *Location) (Time, error)
|
ParseInLocation类似Parse但有两个重要的不同之处。
- 第一,当缺少时区信息时,Parse将时间解释为UTC时间,而ParseInLocation将返回值的Location设置为loc;
- 第二,当时间字符串提供了时区偏移量信息时,Parse会尝试去匹配本地时区,而ParseInLocation会去匹配loc。
layout
的时间必须是"2006-01-02 15:04:05"
这个时间,当然格式不一定是这个,时间一定得是,这是go诞生的时间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| now := time.Now() fmt.Println(now)
loc, err := time.LoadLocation("Asia/Shanghai") if err != nil { fmt.Println(err) return }
timeObj, err := time.ParseInLocation("2006/01/02 15:04:05", "2019/08/04 14:15:20", loc) if err != nil { fmt.Println(err) return } fmt.Println(timeObj) fmt.Println(timeObj.Sub(now))
|