Go语言时间相关操作标准库time包的使用

2023年 7月 10日 50.3k 0

开发应用程序的过程中,经常需要记录某些操作的时间或者格式化时间戳,因此大部分编程语言都会有操作时间的库,Go语言当然也不例外。

Go语言对时间的操作能力集中标准库time包里,所以在这篇文章中,我们一起来学习time包的使用。

获取当前时间

在Go语言中,要获取当前的时间非常简单,只要调用time包的Now()函数即可:

fmt.Println(time.Now())

上面代码的输出结果是:

2023-06-16 09:44:58.726134 +0800 CST m=+0.000151257

上面结果的各部分意义是:

  • 2023-06-06:表示日期
  • 09:44:58.726134:表示时间
  • +0800 CST:时区,这里是指东八区
  • m=+0.000151257:单调时间,用于表示两个时间点的长度。

时间戳与时区

时区

地球上各个地区因为经度的不同被划分为24个时区,这24个时区以零时区(中时区)开始划分为东西各12个时区,相邻两个时区之间相差一个小时,其计算规则是向东每跨过一个时区增加1个小时,向西每跨一个时间减去1个小时:

Go语言时间相关操作标准库time包的使用

假设此时零时区是上午9:00的话,那么其他各个时区的时间根据所在时区会有所不同,下面表格列举了几个时区的时间:

西七区(加里福利亚州) 西五区(纽约) 西四区(圣地亚哥) 零时区 泰国(东7区) 中国(东八区) 日本(东九区)
1:00 4:00 7:00 9:00 16:00 17:00 18:00

世界标准时间的缩写为UTCUTC也表示零时区,如果我们想表示某个时区的话,比如东八区,其写法为UTC+8,西五区则为UTC-5

另外,时区一般有自己的缩写,比如PRC表示中国标准时间,Asia/Shanghai也是指中国时间,也就是说PRCAsia/ShanghaiUTC+8都是表示东八区的中国时间。

时间戳

时间戳是指以格林尼治1970年1月1日 00:00:00为起点的秒数,时间戳不受时区的影响,所在在地球上任何一个地方在某一时刻获得的时间戳都是一样的。

Go语言中,要获得当前时间戳也非常简单:

fmt.Println(time.Now().Unix())

time.Time

Time

前面我们通过time.Now()获取当前时间,实际上该函数返回一个time包下的Time结构体,Time结构体表示一个时间对象,大部分操作时间的功能都集中在这个结构体中:

time.Now().Year() //获取当前年份
time.Now().Month() //获取当前月份

时间格式规则

有了表示时间的对象后,如果想按照我们想要的格式输出可以调用TimeFormat()方法,如果你接触过其他编程语言(比如PHP),这时可能会觉得需要给Format()传进入类似下面的参数:

Y-m-d H:i:s

在上面给出的格式中,Y表示年份,m表示月份,d表示日期,H表示小时,i表示分钟,s表示秒。

在其他编程语言中,使用以上格式进行时间格式化处理,会得到下面这样的日期:

2023-06-18 18:32:30

不过在Go语言中,要想将得到同样的结果,你需要这样做:

time.Now().Format("2006-01-02 15:04:05")

上面的代码的运行结果同样是:

2023-06-18 18:32:30

从上面的格式可以看出2006-01-02 15:04:05相当于其他编程语言的Y-m-d H:i:s,这就是Go语言在时间处理方面与其他编程语言的差异。

Go语言格式化时间的规则如下表格所示:

格式 说明
2006或者06
January或01或1
Mon或者Monday 星期
2或_2或者02 日期
__2或002 一年中的第几天
15或3或03 小时
4或04 分钟
5或05
PM AM/PM
-0700 时区,±hhmm
-07:00 时区,±hh:mm
-07 时区,±hh
-070000 时区, ±hhmmss
-07:00:00 时区, ±hh:mm:ss

因此,如果我们想把当前时间按下面的时间格式显示的话:

年-月-日 时:分:秒 星期几 时区

我们的代码需要这样写:

time.Now().Format("2006-01-02 15:04:05 Monday -0700")

其实,如果总是需要自己写上面的格式字符串也很麻烦,因此time包下定义了很多常量,可以直接调用:

Layout      = "01/02 03:04:05PM '06 -0700" 
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" 
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"
RFC3339     = "2006-01-02T15:04:05Z07:00"
RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
Kitchen     = "3:04PM"
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"
DateTime   = "2006-01-02 15:04:05"
DateOnly   = "2006-01-02"
TimeOnly   = "15:04:05"

Date

如果不是想获取当前时间,而是要指定某个时间,可以调用Date()函数构建一个指定日期Time对象,Date()函数的签名如下:

func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time

可以看到,调用函数Date()需要的参数可以精确到纳秒:

fmt.Println(time.Date(2023, time.Month(1), 2, 2, 2, 2, 0, time.Local))

Parse

有时候我们接收用户与时间相关请求参数时,得到往往是一个时间格式的字符串,比如2023-06-02 10:00:00

t, _ := time.Parse(time.DateTime, "2023-06-02 10:00:00")
fmt.Println(t.Unix())

格式化时间戳

通常我们都是以时间戳的形式将时间保存在数据库中,当需要展示给用户时,则需要将时间戳格式化,Go语言支持秒,毫秒,微秒等时间戳的格式:

t := time.Unix(1685700000, 0)
fmt.Println(t.Format(time.DateTime))

按时区显示时间

有时候我们需要根据用户所在时区显示对应的时间,在time包里,用Location结构体表示一个时区对象,可以使用time包的LoadLocation()函数加载本地预先定义的时区数据

loc1, err := time.LoadLocation("Asia/Shanghai")
loc2, err := time.LoadLocation("PRC")

也可以使用FixeZone函数自己定义一个时区名称:

 beijing := time.FixedZone("Beijing", +8*60*60)

有了Location对象,我们可以将显示不同时区的时间:

package main

import (
 "fmt"
 "time"
)

func main() {
 ch, _ := time.LoadLocation("PRC")
 t := time.Date(2023, time.June, 19, 11, 43, 0, 0, ch)
 fmt.Println("中国时间是:", t)
 jp := time.FixedZone("jp", +(9 * 60 * 60))
 t2 := t.In(jp)
 fmt.Println("日本时间是:", t2)
}

time.Duration

如果要比较两个时刻之间的时间长度,可以调用Time的Sub方法,这个函数可以计算两个时刻的长度,并返回一个表示时间段的Duration结构体:

package main

import (
 "fmt"
 "time"
)

func main() {
 t1, _ := time.Parse(time.DateTime, "2023-06-01 16:00:00")
 t2, _ := time.Parse(time.DateTime, "2023-06-02 16:00:00")
 d := t2.Sub(t1)
 fmt.Println(d)
}

上面例子运行结果为:

24h0m0s

当我们想在某个时刻上叠加一个时间段时,也可以调用time包的ParseDuration()函数构建一个Duration结构体并传给Time结构体的Add()方法。

ParseDuration()函数的参数为一个表示时间段的字符串,比如1h2days

package main

import (
 "fmt"
 "time"
)

func main() {
 d, _ := time.ParseDuration("4h")
 t := time.Now().Add(d)
 fmt.Println(t)
}

小结

Go的标准库time包提供了完整操作对时间的格式式和测量等功能,虽然用法与其他编程语言稍有差异,但是也非常容易掌握。

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论