这是我参与「第五届青训营 」伴学笔记创作活动的第 8 天
时间和日期是我们编程中经常会用到的,本文主要介绍了 Go 语言内置的 time 包的基本用法。time 包提供了一些关于时间显示和测量用的函数。
1如何正确表示时间?
公认最准确的计算应该是使用“原子震荡周期”所计算的物理时钟了(Atomic Clock, 也被称为原子钟),这也被定义为标准时间(International Atomic Time)。
而我们常常看见的 UTC(Universal Time Coordinated,世界协调时间)就是利用这种 Atomic Clock 为基准所定义出来的正确时间。UTC 标准时间是以 GMT(Greenwich Mean Time,格林尼治时间)这个时区为主,所以本地时间与 UTC 时间的时差就是本地时间与 GMT 时间的时差。
UTC + 时区差 = 本地时间
国内一般使用的是北京时间,与 UTC 的时间关系如下:
UTC + 8 个小时 = 北京时间
在Go语言的 time 包里面有两个时区变量,如下:
- time.UTC:UTC 时间
- time.Local:本地时间
同时,Go语言还提供了 LoadLocation 方法和 FixedZone 方法来获取时区变量,如下:
FixedZone(name string, offset int) *Location
其中,name 为时区名称,offset 是与 UTC 之前的时差。
LoadLocation(name string) (*Location, error)
其中,name 为时区的名字。
// 中国没有夏令时,使用一个固定的8小时的UTC时差。
// 对于很多其他国家需要考虑夏令时。
secondsEastOfUTC := int((8 * time.Hour).Seconds())
// FixedZone 返回始终使用给定区域名称和偏移量(UTC 以东秒)的 Location。
beijing := time.FixedZone("Beijing Time", secondsEastOfUTC)
// 如果当前系统有时区数据库,则可以加载一个位置得到对应的时区
// 例如,加载纽约所在的时区
newYork, err := time.LoadLocation("America/New_York") // UTC-05:00
2时间戳
时间戳是自 1970 年 1 月 1 日(08:00:00GMT)至当前时间的总毫秒数,它也被称为 Unix 时间戳(UnixTimestamp)
// timestampDemo 时间戳
func timestampDemo() {
now := time.Now() // 获取当前时间
timestamp := now.Unix() // 秒级时间戳
milli := now.UnixMilli() // 毫秒时间戳 Go1.17+
micro := now.UnixMicro() // 微秒时间戳 Go1.17+
nano := now.UnixNano() // 纳秒时间戳
fmt.Println(timestamp, milli, micro, nano)
}
3时间格式化
时间类型有一个自带的 time.Format 方法进行格式化,需要注意的是Go语言中格式化时间模板不是常见的Y-m-d H:M:S ,。
而是使用 2006-01-02 15:04:05.000(记忆口诀为 6 1 2 3 4 5 )。
- 如果想格式化为12小时格式,需在格式化布局中添加
PM。- 小数部分想保留指定位数就写0,如果想省略末尾可能的0就写 9。
// formatDemo 时间格式化
func formatDemo() {
now := time.Now()
// 格式化的模板为 2006-01-02 15:04:05
// 24小时制
fmt.Println(now.Format("2006-01-02 15:04:05.000 Mon Jan"))
// 12小时制
fmt.Println(now.Format("2006-01-02 03:04:05.000 PM Mon Jan"))
// 小数点后写0,因为有3个0所以格式化输出的结果也保留3位小数
fmt.Println(now.Format("2006/01/02 15:04:05.000")) // 2022/02/27 00:10:42.960
// 小数点后写9,会省略末尾可能出现的0
fmt.Println(now.Format("2006/01/02 15:04:05.999")) // 2022/02/27 00:10:42.96
// 只格式化时分秒部分
fmt.Println(now.Format("15:04:05"))
// 只格式化日期部分
fmt.Println(now.Format("2006.01.02"))
}
4时间格式的转换
1 时间戳转时间字符串 (int64 —> string)
timeUnix:=time.Now().Unix() //已知的时间戳
formatTimeStr:=time.Unix(timeUnix,0).Format("2006-01-02 15:04:05")
fmt.Println(formatTimeStr) //打印结果:2023-02-20 13:30:39
2 时间字符串转时间(string —> Time)
formatTimeStr=”2023-02-20 13:30:39”
formatTime,err:=time.Parse("2006-01-02 15:04:05",formatTimeStr)
if err==nil{
fmt.Println(formatTime) //打印结果:2023-02-20 13:30:39 +0000 UTC
}
3 时间字符串转时间戳 (string —> int64)
// ======= 将时间字符串转换为时间戳 =======
timeTemplate1 := "2006-01-02 15:04:05"
t1 := "2019-01-08 13:50:30" //外部传入的时间字符串
stamp, _ := time.ParseInLocation(timeTemplate1, t1, time.Local) //使用parseInLocation将字符串格式化返回本地时区时间
log.Println(stamp.Unix()) //输出:1546926630
4 时间戳获取日期
// 获取时间,该时间带有时区等信息,获取的为当前地区所用时区的时间
timeNow := time.Now()
// 获取时间戳
unix := time.Now().Unix()
// 获取UTC时区的时间
utcTime := time.Now().UTC()
// go语言固定日期模版
timeLayout := "2006-01-02 15:04:05"
// time.Unix的第二个参数传递0或10结果一样,因为都不大于1e9
timeStr := time.Unix(unix, 0).Format(timeLayout)
fmt.Println(timeNow, unix, utcTime, timeStr)
// 获取年月日,其中month为string,也就是英文的月份
year, month, day := time.Now().Date()
fmt.Printf("year is %+v, month is %+v, day is %+v \n", year, month, day)
补充
根据mysql中timestamp字段获取时间字符串
如下实例,其中lectureModel的create_time字段为timestamp
lecture, err := ll.lectureModel.FindOne(req.LectureId)
// 获取当前时区unix时需要减去3600*8,原因是mysql存储的时间为UTC时间
unixT := lecture.CreateTime.Unix() - 3600*8
timeStr := time.Unix(unixT, 0).Format(DateDetailLayout)
参考资料:
[go语言时间和时间戳转换][www.cnblogs.com/akidongzi/p…]
[Go语言基础之time包][www.liwenzhou.com/posts/Go/go…]