go 中 time 包的使用
time 包中的类型
time 包中定义了以下时间类型:
time.Time{}
时间类型,包含了秒和纳秒以及 Location:
type Time struct {
wall uint64 // 秒
ext int64 // 纳秒
loc *Location
}
time.Month()
月份,定义了十二个月份的常量:
type Month int
const (
January Month = 1 + iota
February
March
April
May
June
July
August
September
October
November
December
)
time.Weekday
月份,定义了十二个月的常量:
type Weekday int
const (
Sunday Weekday = iota
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
)
time.Duration
持续时间,定义了以下持续时间类型,多用于时间的加减:
// 持续时间表示两个瞬间之间经过的时间,以int64纳秒为单位。
// 该表示将最大可表示持续时间限制为大约290年。
type Duration int64
const (
minDuration Duration = -1 << 63
maxDuration Duration = 1<<63 - 1
)
const (
Nanosecond Duration = 1
Microsecond = 1000 * Nanosecond
Millisecond = 1000 * Microsecond
Second = 1000 * Millisecond
Minute = 60 * Second
Hour = 60 * Minute
)
time.Location
在 time 包里有两个时区变量:
- time.UTC:utc 时间
- time.Local:本地时间
另外,还提供了一个 FixedZone
函数,用于设置时区名,以及与 UTC0 的时间偏差,返回 Location:
func FixedZone(name string, offset int) *Location {
l := &Location{
name: name,
zone: []zone{{name, offset, false}},
tx: []zoneTrans{{alpha, 0, false, false}},
cacheStart: alpha,
cacheEnd: omega,
}
l.cacheZone = &l.zone[0]
return l
}
time.Timer 定时器
传达一次到期事件:
type Timer struct {
C <-chan Time
r runtimeTimer
}
time.Ticker 断续器
周期性的传达到期事件的装置。
与定时器的区别:定时器只会传达一次到期事件,断续器会持续工作直到停止
type Ticker struct {
C <-chan Time // The channel on which the ticks are delivered.
r runtimeTimer
}
time 包中的常用函数
Time 类型下的常用函数
- After(u Time) bool:时间类型比较,是否在 Time 之后
- Before(u Time) bool:时间类型比较,是否在 Time 之前
- Equal(u Time) bool:比较两个时间是否相等
- IsZero() bool:判断时间是否为零值,如果 sec 和 nsec 两个属性都是 0 的话,则该时间类型就是 0
- **Date() (yeat int,month Month,day int)**:返回年,月,日三个参数
- Year() int:返回年份
- Month() int:返回月份
- Day() int:返回多少号
- Weekday() Weekday:返回星期几,是 Weekday 类型
- **ISOWeek() (year,week int)**:返回年份以及该天在这年的第几周
- **Clock() (hour,min,sec int)**:返回小时,分钟,秒
- Hour() int:返回小时
- Minute() int:返回分钟
- Second() int:返回秒数
- Nanosecond() int:返回纳秒
- Unix() int64:返回时间戳,自 1970 年 1 月 1 号到现在的秒数
- UnixNano() int64:返回时间戳,包含纳秒数
- Format(layout string) string:将时间转换为一个格式
- Add(d Duration) Time:为一个时间添加一段时间,可以精确到纳秒
- Sub(u Time) Duration:计算两个时间的时间差
- AddDate(years int,months int,days int) Time:添加时间,以年月日为参数
- UTC() Time:设置 location 为 UTC,然后返回时间(相当于 utc0,比中国晚 8 个小时)
- Local() Time:设置 location 为本地时间,就是电脑时间
- **In(loc *Location) Time:**设置 location 为指定的 location
- **Location() *Location**:获取时间的 Location,如果是 nic,则返回 UTC,如果为空,则代表本地
- **Zone() (name string,offset int)**:返回时区,以及与 utc 的时间偏差
其他常用函数
- **time.Now()**:返回当前时间,返回 Time 类型
- time.Sleep(d Duration):表示沉睡多少时间,此时处于阻塞状态
- time.Since(t Time) Duration:返回与当前时间的时间差,t 一般为过去时间
- time.Unix(sec int64,nesc int64) Time:根据秒数和纳秒,返回 Time 类型。如只有一个参数,则另外一个参数默认为 0。
- time.Until(t Time) Duration:计算 t 到当前时间的时间差,t 一般为未来时间
- time.After(d Duration) <-chan Time:返回一个
time.C
这个管道,d 时间间隔后会在此管道中放入一个时间点(time.Now()
) - **time.AfterFunc(d Duration,f func()) *Timer**:将一个时间间隔和一个函数传给 AfterFunc 之后,间隔时间过后将执行传入的函数,只执行一遍
- **time.NewTimer(d Duration) *Timer:**创建一个新的定时器,定时时间为 d
- **time.Parse(layout,value string) (Time,error)**:将字符串转化为 Time 类型。
- **time.ParseDuration(s string) (Duration,error)**:将字符串(”ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”)转化为 Duration 类型
- **time.ParseInLocation(layout,value string,loc *Location) (Time,error)**:ParseInLocation 类似于Parse,但在两个重要方面有所不同:
- 首先,在没有时区信息的情况下,Parse将时间解释为 UTC,ParseInLocation 将时间解释为给定位置。
- 其次,当给定区域偏移量或缩写时,Parse 会尝试将其与本地位置进行匹配。 ParseInLocation 使用给定的位置。
- **time.NewTicker(d Duration) *Ticker**:创建一个新的 Ticker
- time.Tick(d Duration) <-chan Time:返回一个 time.C 管道,d 时间间隔后会在此管道中放入一个时间点(time.Now())
- **time.Date(yeat int,month Month,day,hour,min,sec,nsec int,lo *Location) Time**:设置年月日,返回 Time 类型
- **time.LoadLocation(name string) (*Location,error)**:返回给定名称的位置
- **time.FixedZone(name string,offset int) *Location:**返回给定名称和偏移量的位置
time 包的实际用例
创建时间
获取当前时间
now := time.Now()
创建指定的时间
func main() {
date := time.Date(2008,8,8,21,22,23,456234,time.UTC)
fmt.Printf("date is %s\n", date)
date = time.Now().UTC()
fmt.Printf("current date is %s",date)
}
输出如下:
date is 2008-08-08 21:22:23.000456234 +0000 UTC
current date is 2021-03-23 06:58:28.054182 +0000 UTC
纳秒/毫秒/秒转换
fmt.Println(ns / 1e6) // 纳秒转毫秒
fmt.Println(ns / 1e9) // 纳秒转秒
时间格式化(time 与 string 相互转换)
Go 不使用 yyyy-mm-dd
布局来格式化时间。而是通过传入一个 string 类型的 layout
布局参数,该参数定义的时间节点为:
// 2006-01-02 15:04:05
Mon Jan 2 15:04:05 -0700 MST 2006
const (
// 定义的时间节点必须符合布局参数定义
layoutISO = "2006-01-02 15:04:05"
layoutUS = "January 2, 2006"
)
func main() {
// string 转 time
date := "2021-03-23"
t, _ := time.Parse(layoutISO, date)
fmt.Println(t)
// time 转 string
now := time.Now()
fmt.Println(now.Format(layoutUS))
fmt.Println(now.Format(layoutISO))
}
time.Parse
:解析日期字符串Format
:格式化time.Time
函数签名如下:
func Parse(layout, value string) (Time, error)
func (t Time) Format(layout string) string
另外,Go 在 time 包中为常用的格式提供了一些便捷的常量:
const (
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" // RFC822 with numeric zone
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" // RFC1123 with numeric zone
RFC3339 = "2006-01-02T15:04:05Z07:00"
RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
Kitchen = "3:04PM"
// Handy time stamps.
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"
)
对时间进行加减运算
加法
func main() {
date := time.Date(2008,8,8,21,22,23,456234,time.UTC)
nextDate := date.AddDate(0,0,1)
nextDateByHour := date.Add(+time.Hour * 24)
previousDate := date.Add(-time.Hour * 24)
fmt.Printf("date is %s\n",date)
fmt.Printf("next date is %s\n",nextDate)
fmt.Printf("next date by add hour is %s\n",nextDateByHour)
fmt.Printf("privious date by add hour is %s\n",previousDate)
}
输出结果如下:
date is 2008-08-08 21:22:23.000456234 +0000 UTC
next date is 2008-08-09 21:22:23.000456234 +0000 UTC
next date by add hour is 2008-08-09 21:22:23.000456234 +0000 UTC
privious date by add hour is 2008-08-07 21:22:23.000456234 +0000 UTC
减法
func main() {
start := time.Now()
time.Sleep(1*time.Second)
stop := time.Now()
cost := stop.Sub(start)
fmt.Printf("The call took %v to run.\n",cost)
}
输出结果如下:
The call took 1.000541262s to run.
时间戳与Time相互转换
Time
类具有 Unix()
方法,可以将时间转换为 glang 中的 UNIX 时间戳:
func main() {
now := time.Now().Unix() // 秒数
nowNano := time.Now().UnixNano() // 纳秒数
// now is 1616484297
fmt.Printf("now is %v\n",now)
// nowNano is 1616484297027772000
fmt.Printf("nowNano is %v\n",nowNano)
}
Unix 时间戳转 Time 格式:通过 time.Unix
函数
func main() {
now := time.Unix(time.Now().Unix(), 0)
fmt.Printf("now is %v\n",now)
}
输出结果如下:
now is 2021-03-23 15:32:41 +0800 CST
在本地和其他时区使用时间戳获取当前日期和时间
LoadLocatio
返回具有给定名称的 Location
:
func main() {
t := time.Now()
fmt.Println("Location: ", t.Location(), " Time: ", t)
location, _ := time.LoadLocation("America/New_York")
// 转换时区
tInAmerica := t.In(location)
fmt.Println("Location: ", location, " Time: ", tInAmerica)
location, _ = time.LoadLocation("Asia/Shanghai")
tInShanghai := t.In(location)
fmt.Println("Location: ", location, " Time: ", tInShanghai)
}
输出结果:
Location: Local Time: 2021-03-23 21:46:37.255412 +0800 CST m=+0.000090396
Location: America/New_York Time: 2021-03-23 09:46:37.255412 -0400 EDT
Location: Asia/Shanghai Time: 2021-03-23 21:46:37.255412 +0800 CST
获取 Weekday 和 Yearday
Weekday 返回由 t 指定的星期几。Yearday 返回由 t 指定的一年中的第几天,非闰年范围为 [1,365]
,闰年为 [1,366]
。
func main() {
t, _ := time.Parse("2006 01 02 15 04", "2015 11 11 16 50")
fmt.Println(t.YearDay()) // 315
fmt.Println(t.Weekday()) // Wednesday
t, _ = time.Parse("2006 01 02 15 04", "2011 01 01 0 00")
fmt.Println(t.YearDay()) // 1
fmt.Println(t.Weekday()) // Saturday
}
日期时间的前后关系判断
func main() {
t1 := time.Now()
t2 := t1.Add(time.Minute)
t3 := t1.Add(-time.Minute)
if t1.Before(t2) {
fmt.Println("t1 is before t2")
} else {
fmt.Println("t1 is after t2")
}
fmt.Println(time.Since(t3))
}
输出结果如下:
t1 is before t2
1m0.000028295s
定时器
func main() {
go func() {
timer := time.NewTimer(2 * time.Second)
for t := range timer.C:
fmt.Println("timer fired")
}
}
}()
time.Sleep(3 * time.Second)
}
断续器(每个固定的时间执行一次)
func main() {
ticker := time.NewTicker(1 * time.Second)
go func() {
for t := range ticker.C:
fmt.Println("ticker at: ", t)
}
}
}()
time.Sleep(10 * time.Second)
}
ticker at: 2021-03-23 22:19:49.743301 +0800 CST m=+1.003682073
ticker at: 2021-03-23 22:19:50.741223 +0800 CST m=+2.001600968
ticker at: 2021-03-23 22:19:51.744963 +0800 CST m=+3.005338145
ticker at: 2021-03-23 22:19:52.742212 +0800 CST m=+4.002584520
ticker at: 2021-03-23 22:19:53.741429 +0800 CST m=+5.001799684
ticker at: 2021-03-23 22:19:54.742483 +0800 CST m=+6.002850379
ticker at: 2021-03-23 22:19:55.741314 +0800 CST m=+7.001678696
ticker at: 2021-03-23 22:19:56.743402 +0800 CST m=+8.003764744
ticker at: 2021-03-23 22:19:57.740211 +0800 CST m=+9.000570923
参考资料: