Go语言中日期和时间处理的完全指南

发表时间: 2024-04-30 15:01

实例1: 获取unix时间、日期和时间

package mainimport ("fmt""time")func main() {    fmt.Println(time.Now().Unix()) //1543760094 unix时间戳    fmt.Println(time.Now().Format("2006-01-02")) //2006-01-02 固定的写法, 写其他数字会不准确    fmt.Println(time.Now().Format("2006-01-02 15:04:05"))//2006-01-02 15:04:05 固定的写法, 写其他数字会不准确    time.Now().Format("20060102150405") //20181213225944    fmt.Println(time.Now().UTC()) //2019-11-29 07:47:47.7945708 +0000 UTC}

实例2: 指定一个时间

package mainimport (    "fmt"    "time")func main() {    fmt.Println(time.Date(2017, 02, 27, 20, 20, 20, 20, time.Local)) //2017-02-27 20:20:20.00000002 +0800 CST    fmt.Println(time.Date(2017, 02, 27, 20, 20, 20, 20, time.UTC)) //2017-02-27 20:20:20.00000002 +0000 UTC    fmt.Println(time.Date(2017, 02, 27, 20, 20, 20, 20, time.Local).Unix()) //1488198020 unix时间戳    fmt.Println(time.Date(2017, 02, 27, 20, 20, 20, 20, time.Local).Format("2006-01-02 15:04:05")) //2017-02-27 20:20:20}

注意: Local代表系统本地, 对应本地时区。

UTC代表通用协调时间, 对应零时区。

CST: 中部标准时间, CST可以为如下4个不同的时区的缩写:

美国中部时间:Central Standard Time (USA) UT-6:00

澳大利亚中部时间:Central Standard Time (Australia) UT+9:30

中国标准时间:China Standard Time UT+8:00

古巴标准时间:Cuba Standard Time UT-4:00

实例3: 字符串转时间戳

package mainimport ("fmt""time")func main() {    x := "2018-12-02 17:30:20"    p, err := time.Parse("2006-01-02 15:04:05", x) //time.Parse 把时间字符串转换为Time, 时区是UTC时区。    if err != nil {    fmt.Println("time parse ", err)    }    fmt.Println(p) //2018-12-02 17:30:20 +0000 UTC    fmt.Println(p.Unix()) //1543771820}

实例4: 将时间戳转换成标准datetime时间

package mainimport (    "fmt"    "time")func main() {    fmt.Println(time.Unix(1543760387, 0)) //2018-12-02 22:19:47 +0800 CST    fmt.Println(time.Unix(1543760387, 0).Format("2006-01-02 15:04:05")) //2018-12-02 22:19:47    timestamp := time.Now().Unix() //time.Now() 返回Time类型值 代表一个纳秒精度的时间点。    fmt.Println(time.Unix(timestamp, 0)) //2018-12-02 22:33:19 +0800 CST}

实例5: 如何设置时区

package mainimport (    "fmt"    "time")func main() {    zonetime, _ := time.LoadLocation("Asia/Shanghai")    fmt.Println(time.Now().In(zonetime)) //2019-12-02 15:48:09.1680766 +0800 CST    zonetime, _ = time.LoadLocation("America/Adak")    fmt.Println(time.Now().In(zonetime)) //2019-12-01 21:48:09.1680766 -1000 HST    fmt.Println(time.Now().In(zonetime).Unix()) //1575272889}

所有的时区名字可以在$
GOROOT/lib/time/zoneinfo.zip文件中找到, 解压zoneinfo.zip可以得到一堆目录和文件, 我们只需要目录和文件的名字, 时区名是目录名+文件名,

比如"Asia/Shanghai"。中国时区名只有"Asia/Shanghai"和"Asia/Chongqing", 而没有"Asia/Beijing"。

实例6: 使用time.Since计算执行时间

想要获取计算某个任务从开始到结束的运行时间, 我们可以使用time包中的Slice函数

package mainimport ("fmt""time")func main() {    start := time.Now() // 获取当前时间    sum := 0    for i := 0; i < 100000000; i++ {        sum++    }    elapsed := time.Since(start)    fmt.Println("该函数执行完成耗时:", elapsed)}

我们执行100000000次的加操作,time.Now 获取当前的时间, time.Since可以计算出一个事件戳到当前的时间差。

运行结果如下:

该函数执行完成耗时: 39.8933ms


实例7: 使用time.Now().Sub()计算时间差

我们只需将time.Since()替换成 time.Now().Sub() 即可, 如下:

package mainimport (    "fmt"    "time")func main() {    start := time.Now() // 获取当前时间    sum := 0    for i := 0; i < 100000000; i++ {    sum++    }    elapsed := time.Now().Sub(start)    fmt.Println("该函数执行完成耗时:", elapsed)}

其实time.Since内部调用了Sub函数, 我们进入time包看, 注释的意思是, Since返回从t开始经过的时间, time.Since 是 time.Now().Sub(t) 的简写方式

// Since returns the time elapsed since t.// It is shorthand for time.Now().Sub(t).func Since(t Time) Duration {    var now Time    if t.wall&hasMonotonic != 0 {        // Common case optimization: if t has monotonic time, then Sub will use only it.        now = Time{hasMonotonic, runtimeNano() - startNano, nil}    } else {        now = Now()    }        return now.Sub(t)}

当我们也可以使用 time.Now().Sub(start).Seconds()获取经过多少秒,Hours获取经过的小时数等,对应的也可以简写为time.Since(start).Seconds()、time.Since(start).Seconds()等。

关于时间单位:

type Durationtype Duration int64

Duration类型代表两个时间点之间经过的时间, 以纳秒为单位。可表示的最长时间段大约290年。

const (    Nanosecond Duration = 1    Microsecond = 1000 * Nanosecond    Millisecond = 1000 * Microsecond    Second = 1000 * Millisecond    Minute = 60 * Second    Hour = 60 * Minute)

常用的时间段。没有定义一天或超过一天的单元, 以避免夏时制的时区切换的混乱。

要将Duration类型值表示为某时间单元的个数, 用除法:

second := time.Secondfmt.Print(int64(second/time.Millisecond)) // prints 1000

要将整数个某时间单元表示为Duration类型值,用乘法:

seconds := 10fmt.Print(time.Duration(seconds)*time.Second) // prints 10s

如:

//func (r *Rand) Intn(n int) int 返回一个取值范围在[0,n)的伪随机int值,如果n<=0会panic。time.Sleep(time.Duration(rand.Intn(1500)) * time.Microsecond)

实例8: 随机数

package mainimport ("fmt""math/rand""time")func generator() chan int {    out := make(chan int)    i := 0    go func() {        for {            //func (r *Rand) Intn(n int) int 返回一个取值范围在[0,n)的伪随机int值,如果n<=0会panic。            time.Sleep(time.Duration(rand.Intn(1500)) * time.Microsecond)            out <- i            i++        }    }()    return out}func main() {    //var c1, c2 chan int // c1 and c2 = nil    var c1, c2 = generator(), generator()    for {        select {            case n := <-c1:            fmt.Println("Received from c1:", n)            case n := <-c2:            fmt.Println("Received from c2:", n)        }    }}

实例9: 休眠

package mainimport ("fmt""time")func main() {    fmt.Println("begin")    time.Sleep(time.Duration(2)*time.Second)    // 测试使用简写也是可以达到效果 如果不是数字变量 则必须写上 time.Duration    // time.Sleep(2 *time.Second)    fmt.Println("end")}


常见的问题: 时间与数字相乘的问题

时间与数字相乘, 如果用硬编码的形式直接写是没有问题的:

time.Second * 1000

如果用表达式来写就编译报错了

second := 10000second * time.Secondinvalid operation: second * time.Second (mismatched types int and time.Duration)

官网文档推荐这样写:

second : =10000time.Duration(second) * time.Second