Go 语言中内置的 time 包提供了时间的显示、转换、计算等功能,使用 time 包可以方便地进行时间相关操作。时间,对程序员来说是一个复杂且重要的概念。在代码中如何正确地表示和操作时间,直接影响到程序的行为和结果。Go 语言作为一门优秀的编程语言,它在时间表示和转换方面有着非常强大和人性化的功能。
本文主要内容包括
- Go 语言时间转换基础
- 时间的显示和格式化
- 时间的计算和转换
- 时间字符串解析
- 实际时间转换示例
- 时间处理进阶用法
- time 包的其他用法
- Go语言时间转换完整示例
1
一、Go 语言时间转换基础
Go 语言中内置的 time 包提供了时间的显示、转换、计算等功能,使用 time 包可以方便地进行时间相关操作。
1.1
1. Time 类型
time.Time 类型表示时间点信息,它包含时、分、秒、纳秒、时区等信息。使用 time.Now()可以获取当前时间
now := time.Now() // 获取当前时间
也可以使用 time.Unix()将 Unix 时间戳转换为 Time
t := time.Unix(1660924000, 0) // 将秒级Unix时间戳转换为时间
1.2
2. 时间组成
time.Time 提供了获取时间各个组成部分的方法
hour := t.Hour() // 小时 minute := t.Minute() // 分钟 second := t.Second() // 秒 nanosecond := t.Nanosecond() // 纳秒 year := t.Year() // 年 month := t.Month() // 月 day := t.Day() // 日 weekday := t.Weekday() // 星期几 zone, offset := t.Zone() // 时区信息
这些方法可以获得时间的时分秒、年月日等信息。
1.3
3. 时间比较
可以使用 time.Time 的 Before()、After()、Equal()方法比较两个时间大小
t1 := time.Now() t2 := t1.Add(time.Hour) fmt.Println(t1.Before(t2)) // true fmt.Println(t1.After(t2)) // false fmt.Println(t1.Equal(t2)) // false
time.Time 还可以直接比较大小:if t1.Before(t2) {...}
2
二、时间的显示和格式化
获得 time.Time 后,可以以不同的格式显示时间。
2.1
1. 默认格式
Print 或 Println 直接输出 time.Time,默认以 RFC3339 格式显示
now := time.Now() fmt.Println(now) // 2023-02-20T21:00:00+08:00
2.2
2. 自定义格式化
使用 time.Time 的 Format 方法可以自定义格式化时间显示
const format = "2006-01-02 15:04:05" fmt.Println(now.Format(format)) // 2023-02-20 21:00:05
Format 的参数定义了转换的格式和内容
2006 年份,用4位数表示 01 月份,用2位数表示 02 日期,用2位数表示 15 小时,24小时制,用2位数表示 04 分钟,用2位数表示 05 秒,用2位数表示
通过组合不同的格式值,可以灵活地格式化时间显示。
2.3
3. 标准格式
time 包定义了几种标准的格式化布局常量
- time.ANSIC = "Mon Jan _2 15:04:05 2006"
- time.UnixDate = "Mon Jan _2 15:04:05 MST 2006"
- time.RubyDate = "Mon Jan 02 15:04:05 -0700 2006"
- time.RFC822 = "02 Jan 06 15:04 MST"
- time.RFC822Z = "02 Jan 06 15:04 -0700"
- time.RFC850 = "Monday, 02-Jan-06 15:04:05 MST"
- time.RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
- time.RFC1123Z = "Mon, 02 Jan 2006 15:04:05 -0700"
- time.RFC3339 = "2006-01-02T15:04:05Z07:00"
- time.RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
- time.Kitchen = "3:04PM"
- time.Stamp = "Jan _2 15:04:05"
- time.StampMilli = "Jan _2 15:04:05.000"
- time.StampMicro = "Jan _2 15:04:05.000000"
- time.StampNano = "Jan _2 15:04:05.000000000"
使用这些格式只需要将常量作为参数传入 Format 方法
fmt.Println(now.Format(time.RFC822)) // 02 Feb 23 21:00 +0800
3
三、时间的计算和转换
可以对时间进行计算,获得新的时间,或者转换为其他时间单位。
3.1
1. Add 和 Sub
使用 Add 可以增加时间
t := t.Add(time.Hour * 24) // 增加24小时 t = t.Add(time.Minute * 30) // 增加30分钟
Sub 可以获取两个时间的差值 Duration
t1 := ... t2 := ... diff := t2.Sub(t1) // 获取间隔时间段
3.2
2. UTC 和 Local
UTC()方法可以获取 UTC 时间,Local()方法可以转换为当前位置的时间
now := time.Now() // 当前本地时间 utc := now.UTC() // 转换为UTC时间 local := utc.Local() // 重新转换为本地时间
3.3
3. 时间戳转换
Unix()和 UnixNano()可以获取时间的 Unix 时间戳(秒和纳秒)
now := time.Now() seconds := now.Unix() // 秒级时间戳 nanoseconds := now.UnixNano() // 纳秒时间戳
3.4
4. 睡眠
Sleep 可以使程序睡眠指定时间
time.Sleep(time.Second * 5) // 睡眠5秒
3.5
5. Ticker
Ticker 可以设置定时器,定期发送时间
ticker := time.NewTicker(time.Second * 5) for now := range ticker.C { fmt.Println(now) // 每5秒打印一次时间 }
4
四、时间字符串解析
可以将字符串解析为时间。
4.1
1. Parse 和 ParseInLocation
Parse 解析一个格式化的时间字符串,返回时间
t, err := time.Parse("2006-01-02 15:04:05", "2023-02-20 21:00:00")
ParseInLocation 同时指定时区信息
loc, err := time.LoadLocation("Asia/Shanghai") t, err := time.ParseInLocation("2006-01-02 15:04:05", "2023-02-20 21:00:00", loc)
4.2
2. 标准格式
使用 RFC3339、RFC822 等标准格式的时间字符串可以直接解析
t, err := time.Parse(time.RFC3339, "2023-02-20T21:00:00+08:00")
4.3
3. 错误处理
因为解析可能出错,应该处理解析错误
const layout = "2006-01-02 15:04:05" t, err := time.Parse(layout, "2023-02-20 21:00:00") if err != nil { fmt.Println(err) return } // 使用解析的时间t
5
五、实际时间转换示例
结合上面的知识点,这里提供一些常见的时间转换示例。
5.1
1. Unix 时间戳转换
将 Unix 时间戳秒转换为时间
import "time" seconds := 1660924000 t := time.Unix(seconds, 0) // 使用Unix()从秒时间戳获取时间 fmt.Println(t) // 2023-02-20 21:00:00 +0800 CST
5.2
2. ANSI C 时间格式转换
解析 ANSI C 格式的时间字符串
const ansiCLayout = "Mon Jan _2 15:04:05 2006" str := "Mon Feb 20 21:00:00 2023" t, err := time.Parse(ansiCLayout, str) fmt.Println(t) // 2023-02-20 21:00:00 +0800 CST
5.3
3. 格式化显示时间
格式化显示时间
now := time.Now() const layout = "2006-01-02 15:04:05" fmt.Println(now.Format(layout)) // 2023-02-20 21:00:05
5.4
4. 获取时间字段
获取时间的时分秒等字段
hour := now.Hour() minute := now.Minute() second := now.Second() year := now.Year() month := now.Month() day := now.Day()
5.5
5. 计算时间差
计算两个时间的差值
t1, err := time.Parse("2006-01-02 15:04:05", "2023-02-01 00:00:00") t2, err := time.Parse("2006-01-02 15:04:05", "2023-02-28 00:00:00") diff := t2.Sub(t1) // 27h0m0s
6
六、时间处理进阶用法
这里介绍一些时间处理的进阶用法。
6.1
1. 时区处理
Go 语言中时区处理主要涉及
- LoadLocation 函数加载时区信息
- 时区参数在 ParseInLocation 解析时指定
- time.Time 的 Location 方法获取时区
示例:
loc, err := time.LoadLocation("Asia/Shanghai") t, err := time.ParseInLocation("2006-01-02 15:04:05", "2023-02-20 21:00:00", loc) zone, offset := t.Zone() // 获取时区信息 fmt.Println(t.Location()) // Asia/Shanghai
6.2
2. 定时器
time.Ticker 定期触发时间:
ticker := time.NewTicker(time.Second * 5) for t := range ticker.C { fmt.Println(t) // 每5秒打印一次时间 }
6.3
3. 时间戳转换
time.Unix 和 UnixNano 转换为时间戳
now := time.Now() secs := now.Unix() // 秒时间戳 nanos := now.UnixNano() // 纳秒时间戳
6.4
4. 时间格式化处理
Format 格式化时间显示
t := time.Now() fmt.Println(t.Format("2006-01-02 15:04:05")) // 自定义格式 fmt.Println(t.Format(time.RFC3339)) // 使用RFC3339标准格式
6.5
5. 链式时间计算
时间支持链式操作,可以连续增加时间
t := time.Now() t = t.Add(time.Hour * 24).Add(time.Minute * 30) // 增加1天和30分钟
7
七、time 包的其他用法
time 包中还有一些其他用法
- AfterFunc 和 NewTimer 可以在未来时间做一次性触发
- Date 和 ParseDuration 可以处理日期和时间段
- LoadLocation 可以预加载时区信息
- Sleep 可以使 Goroutine 睡眠指定时间
- Since 和 Until 可以计算时间段序列
详细用法可以查阅 time 包的文档和示例代码。
8
八、Go语言时间转换完整示例
Go 语言中时间转换和格式化的完整示例
package main import ( "fmt" "time" ) func main() { // 1. 将时间戳秒转换为时间 seconds := int64(1660924000) t := time.Unix(seconds, 0) fmt.Println(t) // 2. 解析布局格式的时间字符串 layout := "2006-01-02 15:04:05" t, err := time.Parse(layout, "2023-08-20 11:00:00") if err != nil { fmt.Println(err) return } // 3. 格式化输出时间 fmt.Println(t.Format("2006/01/02 15:04")) // 4. 计算时间差值 t1, _ := time.Parse(layout, "2023-08-01 11:00:00") t2, _ := time.Parse(layout, "2023-08-31 11:00:00") diff := t2.Sub(t1) fmt.Println(diff) // 5. 增加时间 t = t.Add(time.Hour * 24) fmt.Println(t) // 6. 定时器 ticker := time.NewTicker(time.Second * 2) go func() { for t := range ticker.C { fmt.Println("Tick:", t) } }() // 7. 睡眠 time.Sleep(time.Second * 5) ticker.Stop() fmt.Println("Done") }
- 将 Unix 时间戳秒转换为时间
- 解析布局格式的时间字符串
- 使用 Format 格式化输出时间
- 计算两个时间的差值
- 增加时间的小时
- 使用 Ticker 设置定时器定期触发
- 调用 Sleep 使程序睡眠一段时间
这个示例演示了 Go 语言中处理时间的一些常见用法。我们可以通过组合这些用法来实现具体的时间转换、显示、计算等功能。
9
九、总结
在 Go 语言中正确处理时间非常重要,time 提供了完善的时间操作和转换功能。
主要是理解 time.Time 表示时间点,可以通过方法获取时间详情;显示和格式化时间需要定义布局;可以对时间进行计算和转换等。
注意解析时间时区信息,使用 tic.Ticker 定时触发等高级用法。
通过熟练应用 time 包,可以便利地进行各种时间相关处理。
