写点什么

golang 中 time 包使用教程之基础使用篇

作者:Go学堂
  • 2022-11-16
    北京
  • 本文字数:4287 字

    阅读完需:约 14 分钟

golang 中 time 包使用教程之基础使用篇

在编写程序中,我们经常会遇到时间戳和日期字符串相互转换、获取当前时间、时间之间的比较操作。本文主要介绍 golang 中关于时间常用的操作。


golang 中的时间操作在 time 包中。时间操作的基础是基于一个 Time 的结构体。时间相关的操作都需要先转换成 Time 结构体,再通过 Time 结构体相关的函数转换成目标值。如下图:



再来看 Time 结构体在源文件中的定义:


type Time struct {  wall uint64  ext int64  loc *Location}
复制代码

01 获取时间相关操作

1、获取当前时间戳


函数原型:func (t Time) Unix() int64


示例代码:


seconds := time.Now().Unix()
复制代码


获取当前年月日时分秒和星期几(数字不带前导 0)


函数原型:


func (t Time) Date() (yearint, month Month, dayint

func(t Time)Clock() (hour, min, secint)


func(t Time)Hour()int


func(t Time)Minute()int


func(t Time)Second()int


示例代码:


//获取当前时间的Time结构体实例t := time.Now()
//通过Date函数同时获取年月日year, month, day := t.Date()//假设日期为2021-1-7 打印结果为 year:2021, month:1, day:7fmt.Printf("year:%d, month:%d, day:%d\n", year, month, day)
//通过Clock函数同时获取时分秒hour, minute, second := t.Clock()//假设时间是18:51:9 打印结果 hour:18,minute:51,second:9fmt.Printf("hour:%d,minute:%d,second:%d\n", hour, minute, second)
//也可以单独获取年、月、日、时、分、秒、星期几year := t.Year() //获取所属年份month := t.Month() //获取所属月份,不带前导零day := t.Day() //获取所属日,不带前导零hour := t.Hour() //获取当前小时minutes := t.Minute() //获取当前分钟seconds := t.Seconds() //获取当前描述nanosecond := t.Nanosecond() //获取当前纳秒数
复制代码


3、获取今天是星期几


函数原型:func (t Time) Weekday() Weekday


该函数返回值类型是 Weekday,即可以表示成数字星期几,也可以输出成星期的英文表示。


示例代码:


//获取当前时间的Time结构体实例t := time.Now()//获取是星期几, t.Weekday返回的是Weekday类型//Weekday类型在源码的定义是 type Weekday intweekday := t.Weekday()// 打印出星期几的数字表示和英文表示// 假设是星期四,打印结果:weekday=4, weekday(string)=Thursdayfmt.Printf("weekday=%d, weekday(string)=%s\n\n", weekday, weekday)
复制代码


4、返回当前时间是一年中的第几天


函数原型:func (t Time) YearDay() int


示例代码:


//获取当前时间的Time结构体实例t := time.Now()
yearday := time.Now().YearDay()// 假设时间是2021-01-07日 打印结果 yearday = 7fmt.Printf("yearday=%d\n\n", yearday)
复制代码


02 时间戳和日期字符串之间的转换

1、时间戳格式化成日期字符串


函数原型:


func Unix(sec int64, nsec int64) Time


func (t Time) Format(layout string) string


该转换主要分三步:


1、 将时间戳类型转成 int64 类型


2、将 int64 类型时间戳转换成 Time 结构


3、调用 Time 结构体的 Format 函数


示例代码:


// 1、将时间戳转换成int64类型timestamps := int64(1609945385) //该时间戳代表2021-01-06 23:03:05
//2、将int64类型时间戳转换成Time结构,time.Unix函数的第2个参数代表纳秒数t := time.Unix(timestamps, 0)
//3、调用Time结构体的Format函数,这里我们定义一组格式var formats = []string{ "2006年01月02日 15时04分05秒", "2006-01-02 15:04:05", "2006/01/02 15:04:05", "06-01-02", "06年01月02日", "2006.01.02", "06/1/2",}
for _, layout := range formats { result := t.Format(layout) fmt.Printf("日期格式:%s, 转换结果:%s \n", layout, result)}
复制代码


2、日期字符串按格式转换成时间戳


函数原型:funcParseInLocation(layout, valuestring, loc *Location) (Time,error)


该转换主要分三步:


1、调用 time.LoadLocation 函数,设置特定的时区。否则,在第 2 步,默认会按 UTC 时区解析时间。

2、调用 time.ParseInLocation 函数,将字符串转换成 Time 结构体

3、调用 Time 结构体的 Unix 函数转换成对应的时间戳


示例代码:


// 该结构体代表将value按format格式解析成Time结构体实例type ParseFormat struct {    format string // 日期格式    value string // 要转换的日期}//这里定义一组时间格式和要转换的日期字符串var parseFormats = []ParseFormat{    {"2006年01月02日 15时04分05秒", "2021年01月06日 23时03分05秒"},
{"2006-01-02 15:04:05", "2021-01-06 23:03:05"},
{"2006/01/02 15:04:05", "2021/01/06 23:03:05"},
{"06-01-02", "21-01-06"},
{"06年01月02日", "21年01月06日"},
{"2006.01.02", "2021.01.06"},
{"06/1/2", "21/1/6"},}
//1、设置时区为上海,即北京时间loc, _ := time.LoadLocation("Asia/Shanghai")
for _, parseFormat := range parseFormats { // 2、将日期字符串按特定格式转换成特定时区下的Time结构体 t, _ := time.ParseInLocation(parseFormat.format, parseFormat.value, loc) // 3、调用Time结构体的Unix函数转换成对应的时间戳 unix := t.Unix() fmt.Printf("时区:%v, 时间戳(秒):%d\n", t.Location(), unix)}
复制代码

03 时间之间的常用计算操作

这里介绍一个新的数据类型 Duration。在 time 源码包中的定义如下:


type Duration int64
复制代码


Duration,代表的是两个时间点之间的持续时间(纳秒数),即时段。


上文的 Time 结构体类型,代表的是时刻,即一个时间点。如下图:



Duration = t1 - t2 单位:纳秒


1、计算两个日期之间相差多少秒


该转换主要分三步:


a、调用 time.LoadLocation 函数,设置特定的时区。否则,第 2 步默认会按 UTC 时区解析时间。


b、调用 time.ParseInLocation 函数,将字符串转换成 Time 结构体


c、调用 Time 结构体的计算函数 Sub,得到两个时间之间的 Duration


示例代码:


t1str := "2021-01-07 15:57:23"t2str := "2021-01-07 18:57:23"layout := "2006-01-02 15:04:05" //时间字符串的格式//1、将时间字符串转换成Time类型location, _ := time.LoadLocation("Asia/Shanghai")t1 := time.ParseInLocation(layout, t1str, location)t2 := time.ParseInLocation(layout, t2str, location)
//2、计算两个Time结构实例之间的差d := t2.Sub(t1)
//3、根据返回的Duration类型的d转换成相应的小时/分钟/秒数hours := d.Hours() //转换成两个时刻相差的小时数minutes := d.Minutes() //转换成两个时刻相差的分钟数seconds := d.Seconds() //转换成两个时刻相差的秒数milliseconds := d.Milliseconds() //转换成两个时刻相差的毫秒数microseconds := d.Microseconds() //转换成两个时刻相差的微妙数nanoseconds := d.Nanoseconds() //转换成两个时刻相差的纳秒数
复制代码


2、获取从某个时间 至今 经过的时间 Duration


函数原型:funcSince(t Time) Duration


场景:假设你和你女朋友相识于 2014-10-02 13:14:15,计算出至今你们总共认识了多长时间。


示例代码:


t1str := "2014-10-02 13:14:15"layout := "2006-01-02 15:04:05" //时间字符串的格式​//1、将时间字符串转换成Time类型location, _ := time.LoadLocation("Asia/Shanghai")t := time.ParseInLocation(layout, t1str, location)//2、计算两个Time结构实例之间的差d := time.Since(t)//2、根据返回的d转换成响应的小时/分钟/秒数hours := d.Hours() //转换成两个时刻相差的小时数minutes := d.Minutes() //转换成两个时刻相差的分钟数seconds := d.Seconds() //转换成两个时刻相差的秒数milliseconds := d.Milliseconds() //转换成两个时刻相差的毫秒数microseconds := d.Microseconds() //转换成两个时刻相差的微妙数nanoseconds := d.Nanoseconds() //转换成两个时刻相差的纳秒数fmt.Printf("从%s至今你们一起度过了共%d", t1str, d.Round(24*time.Hour))fmt.Printf("从%s至今共一起度过了%f小时\n", t1str, time.Now().Format(layout), hours)
复制代码


3、计算从今天到未来某个时间经过的时间


函数原型:funcUntil(t Time) Duration


示例代码:


t1str := "2021-12-21 13:14:15"layout := "2006-01-02 15:04:05" //时间字符串的格式//第1步,将时间字符串转换成Time类型location, _ := time.LoadLocation("Asia/Shanghai")t := time.ParseInLocation(layout, t1str, location)//第2步,计算两个Time结构实例之间的差d := time.Until(t)//第3步,根据返回的d转换成响应的小时/分钟/秒数hours := d.Hours() //转换成两个时刻相差的小时数fmt.Printf("距女朋友生日%s还有%f小时\n", t1str, hours)
复制代码


4、时间之间的比较:是早、是晚、还是相等


相关函数:


func (t Time) After(u Time) bool


func (t Time) Before(u Time) bool


func (t Time) Equal(u Time) bool


场景:你和女朋友约会,约好 2021-12-12 13:14:15 在餐厅门口见。这时,你看了看手表,在大脑中和约定时间快速的比较了下,判断是来早了还是来晚了


pivot := "2021-12-12 13:14:15"layout := "2006-01-02 15:04:05" //时间字符串的格式//第1步,将时间字符串转换成Time类型location, _ := time.LoadLocation("Asia/Shanghai")pivotT := time.ParseInLocation(layout, t1str, location)
//第2步,获取现在的时间t := time.Now()
//第3步,和约定时间比较下是否来早了if t.Before(pivotT) { fmt.Println("来早了")}
//和约定时间比较一下,看是否来晚了if t.After(pivotT) { fmt.Println("oh,糟糕,来晚了")}
//和约定时间比较一下,一看,刚刚好if t.Equal(pivotT) { fmt.Println("还好,还好,刚刚好")}
复制代码


5、计算 N 天后的时间


函数原型:func(t Time)Add(d Duration) Time


场景:有一天,你女朋友说,3 天后去你家里玩。你赶紧在日历上看看 3 天后的日期,做上了标记。


d := 3 * 24 * time.HourafterNDay := time.Now().Add(d)fmt.Println("3天后的日期是", afterNDay.Format("2006-01-02"))
复制代码

04 总结

    golang中,Time和Duration类型是时间相互转换的载体。时间字符串格式化时的格式必须以2006-01-02 15:14:15这个时间为模板进行格式化。使用该时间的原因是在Posix date命令中是1 2 3 4 5 6。如下:
复制代码


Mon Jan 2 15:04:05 -0700 MST 20060   1   2  3  4  5              6
复制代码


---特别推荐 ---

特别推荐:一个专注 go 项目实战、项目中踩坑经验及避坑指南、各种好玩的 go 工具的公众号。「Go 学堂 」,专注实用性,非常值得大家关注。点击下方公众号卡片,直接关注。关注送《100 个 go 常见的错误》pdf 文档。

用户头像

Go学堂

关注

关注「Go学堂」,学习更多编程知识 2019-08-06 加入

还未添加个人简介

评论

发布
暂无评论
golang 中 time 包使用教程之基础使用篇_Go_Go学堂_InfoQ写作社区