zl程序教程

您现在的位置是:首页 >  其他

当前栏目

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

2023-02-26 09:48:50 时间

在编写程序中,我们经常会遇到时间戳和日期字符串相互转换、获取当前时间、时间之间的比较操作。本文主要介绍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()

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

函数原型:

func (t Time) Date() (year int, month Month, day int)

func (t Time) Clock() (hour, min, sec int)

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:7
fmt.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:9
fmt.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 int
weekday := t.Weekday()
// 打印出星期几的数字表示和英文表示
// 假设是星期四,打印结果:weekday=4, weekday(string)=Thursday
fmt.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 = 7
fmt.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、日期字符串按格式转换成时间戳

函数原型:

func ParseInLocation(layout, value string, 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、计算两个日期之间相差多少秒

该转换主要分三步:

  1. 调用time.LoadLocation函数,设置特定的时区。否则,在第2步,默认会按UTC时区解析时间。
  2. 调用time.ParseInLocation函数,将字符串转换成Time结构体
  3. 调用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、计算从今天到未来某个时间经过的时间

函数原型:func Until(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.Hour

afterNDay := time.Now().Add(d)

fmt.Println("3天后的日期是", afterNDay.Format("2006-01-02"))