在编程中,我们经常会使用到时间和日期相关的方法,这一期我们就来看一看在 Go 中的时间和日期相关的方法。使用 Go 中的时间和日期相关的方法,需要引入 time 包。
在 Go 中,time.Time
类型用于表示时间。
type Time struct {
wall uint64
ext int64
loc *Location
}
time.Time 代表一个纳秒精度的时间点。程序中应使用 time.Time 类型值来保存和传递时间,而不能用指针。time.Time 类型值可以被多个 goroutine 同时使用。时间点可以使用 Before()
、 After()
和 Equal()
方法进行比较。Sub()
方法让两个时间点相减,生成一个 Duration 类型值(代表时间段)。Add()
方法给一个时间点加上一个时间段,生成一个新的 time.Time 类型时间点。
从上面的源码我们知道,每一个 time.Time 都具有一个地点信息(及对应地点的时区信息),当计算时间的表示格式时,如 Format()
、 Hour()
和 Year()
等方法,都会考虑该信息。Local()
、UTC()
和 In()
方法返回一个指定时区(但指向同一时间点)的 time.Time 。修改地点/时区信息只是会改变其表示;不会修改被表示的时间点,因此也不会影响其计算。
使用 time.Now()
方法我们可以获取当前本地时间:
// Now returns the current local time.
func Now() Time {...}
例如:
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println(time.Now())
}
运行上面的程序会输出当前本地时间:
2022-03-03 21:57:39.5130486 +0800 CST m=+0.010532401
使用下面的一些方法我们能获取到日期的特定信息:
time.Date()
:获取时间点 time 对应的年、月、日。time.Clock()
:获取时间点 time 对应的那一天的时、分、秒。time.Year()
:获取时间点 time 对应的年份。time.Month()
:获取时间点 time 对应那一年的月份。time.Day()
:获取时间点 time 对应那一月的第几日。time.ISOWeek()
:获取时间点 time 对应的 ISO 9601 标准下的年份和星期编号。time.YearDay()
:获取时间点 time 对应的那一年的第几天,平年的返回值范围 [1,365] ,闰年 [1,366] 。time.Weekday()
:获取时间点 time 对应的那一周的周几。time.Hour()
:获取时间点 time 对应的那一天的第几小时,范围 [0, 23] 。time.Minute()
:获取时间点 time 对应的那一小时的第几分钟,范围 [0, 59] 。time.Second()
:获取时间点 time 对应的那一分钟的第几秒,范围 [0, 59] 。time.Nanosecond()
:获取时间点 time 对应的那一秒内的纳秒偏移量,范围 [0, 999999999] 。time.Unix()
:Unix 将 time 表示为 Unix 时间,即从时间点 January 1, 1970 UTC 到时间点 time 所经过的时间(单位秒)。time.UnixNano()
:将 time 表示为 Unix 时间,即从时间点 January 1, 1970 UTC 到时间点 time 所经过的时间(单位纳秒)。如果纳秒为单位的 Unix 时间超出了 int64 能表示的范围,结果是未定义的。注意这就意味着 Time 零值调用 UnixNano 方法的话,结果是未定义的。
下面是一个例子:
package main
import (
"fmt"
"time"
)
func main() {
t := time.Now()
fmt.Println(t)
// 2022-03-03 23:40:26.1478777 +0800 CST m=+0.013198301
fmt.Println(t.Date()) // 2022 March 3
fmt.Println(t.Clock()) // 23 40 26
fmt.Println(t.Year()) // 2022
fmt.Println(t.Month()) // March
fmt.Println(t.Day()) // 3
fmt.Println(t.ISOWeek())// 2022 9
fmt.Println(t.YearDay())// 62
fmt.Println(t.Weekday())// Thursday
fmt.Println(t.Hour()) // 23
fmt.Println(t.Minute()) // 40
fmt.Println(t.Second()) // 26
fmt.Println(t.Nanosecond()) // 147877700
fmt.Println(t.Unix()) // 1646322026
fmt.Println(t.UnixNano()) // 1646322026147877700
}
Duration 类型代表两个时间点之间经过的时间,以纳秒为单位。可表示的最长时间段大约 290 年:
type Duration int64
time 包中定义的时间常量:
const (
Nanosecond Duration = 1 // 纳秒
Microsecond = 1000 * Nanosecond // 微秒
Millisecond = 1000 * Microsecond // 毫秒
Second = 1000 * Millisecond // 秒
Minute = 60 * Second // 分钟
Hour = 60 * Minute // 小时
)
使用 time.Date()
方法能返回一个特定时区的时间点:
func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time {...}
month、day、hour、min、sec和nsec的值可能会超出它们的正常范围,在转换前函数会自动将之规范化。如果 loc 为 nil 会 panic 。下面是一个例子:
package main
import (
"fmt"
"time"
)
func main() {
t := time.Date(2022, time.March, 3, 22, 10, 30, 0, time.UTC)
fmt.Println(t)
}
运行后会输出:
2022-03-03 22:10:30 +0000 UTC
time.Equal(u Time)
:判断两个时间是否相同,会考虑时区的影响,因此不同时区标准的时间也可以正确比较。本方法会比较地点和时区信息。time.Before(u Time)
:如果时间点 time 在 u 之前,返回真;否则返回假。time.After(u Time)
:如果时间点 time 在 u 之后,返回真;否则返回假。time.Add(d Duration)
:返回时间点 time+d。time.AddDate(years int, months int, days int)
:返回增加了给出的年份、月份和天数的时间点 Time。time.Sub(u Time)
:返回一个时间段 time-u。
下面是一个例子:
package main
import (
"fmt"
"time"
)
func main() {
t1 := time.Date(2022, 3, 3, 23, 0, 0, 0, time.UTC)
t2 := time.Date(2022, 3, 3, 23, 0, 0, 0, time.UTC)
t3 := time.Date(2022, 3, 4, 5, 6, 7, 0, time.UTC)
fmt.Printf("t1 equal t2? %v\n", t1.Equal(t2)) // t1 equal t2? true
fmt.Printf("t1 equal t3? %v\n", t1.Equal(t3)) // t1 equal t3? false
fmt.Printf("t1 before t2? %v\n", t1.Before(t2)) // t1 before t2? false
fmt.Printf("t1 before t3? %v\n", t1.Before(t3)) // t1 before t3? true
fmt.Printf("t1 after t2? %v\n", t1.After(t2)) // t1 after t2? false
fmt.Printf("t3 after t1? %v\n", t3.After(t1)) // t3 after t1? true
t := time.Now()
fmt.Println(t) // 2022-03-03 23:42:04.1729043 +0800 CST m=+0.013102601
fmt.Println(t.Add(1000000000)) // 2022-03-03 23:42:05.1729043 +0800 CST m=+1.013102601
fmt.Println(t) // 2022-03-03 23:42:04.1729043 +0800 CST m=+0.013102601
fmt.Println(t.AddDate(1, 2, 3)) // 2023-05-06 23:42:04.1729043 +0800 CST
fmt.Println(t3.Sub(t1)) // 6h6m7s
}
我们可以使用 Printf()
或者 SPrintf()
对日期进行格式化,也可以使用 time.Format()
方法完成日期的格式化。下面是一个例子:
package main
import (
"fmt"
"time"
)
func main() {
t := time.Now()
fmt.Printf("当前时间:%d年%d月%d日 %d时%d分%d秒\n",
t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Minute())
// 当前时间:2022年3月3日 23时49分49秒
dataStr := fmt.Sprintf("当前时间:%d年%d月%d日 %d时%d分%d秒\n",
t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Minute())
fmt.Printf("dataStr = %v", dataStr)
// dataStr = 当前时间:2022年3月3日 23时49分49秒
fmt.Printf(t.Format("2006-01-02 15:04:05"))
// 2022-03-03 23:49:26
fmt.Println()
fmt.Printf(t.Format("15:04:05"))
// 23:49:26
}
注意:上面格式化日期代码中的日期必须是 2006年1月2日15时4分5秒
!