5、time

time包提供了时间的显示和测量用的函数。日历的计算采用的是公历。

基本使用

package main

import (
	"fmt"
	"time"
)

func main() {
	// 获取当前时间,返回一个time.Time类型的实例
	now := time.Now()
	// 原格式输出
	fmt.Println(now) // 2021-01-25 11:07:26.762506 +0800 CST m=+0.000160460

	// 获取年月日时分秒
	year := now.Year()
	month := now.Month()
	day := now.Day()
	hour := now.Hour()
	minute := now.Minute()
	second := now.Second()
	fmt.Printf("%d年%02d月%02d日 %02d时%02d分%02d秒", year, month, day, hour, minute, second) // 2021年01月25日 11时07分26秒
}

Time与字符串转换

time.Time时间类型有一个自带的方法Format()进行格式化,需要注意的是Go语言中格式化时间模板不是常见的Y-m-d H:M:S而是使用Go的诞生时间2006年1月2号15点04分05秒(记忆口诀为2006 1 2 3 4 5)。

其中1、2、3、4、5,前面可以补0来代表结果的保留位数

time.Time转字符串

package main

import (
	"fmt"
	"time"
)

func main() {
	now := time.Now()

	// 格式化,并且hour为24小时制
	s1 := now.Format("2006-01-02 15:04:05") // 2021-01-25 16:11:56
	fmt.Println(s1)
	// 格式化并且hour为12小时制
	s2 := now.Format("2006-01-02 03:04:05") // 2021-01-25 04:11:56
	fmt.Println(s2)
}

字符串转time.Time

package main

import (
	"fmt"
	"time"
)

func main() {
	s1 := "2021-10-20 09:12:13"
	// 默认以UTC时区
	t1, err := time.Parse("2006-01-02 03:04:05", s1)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(t1) // 2021-10-20 09:12:13 +0000 UTC

	// 自定义时区
	loc, err := time.LoadLocation("Asia/Shanghai")
	if err != nil {
		fmt.Println(err)
	}
	t2, err := time.ParseInLocation("2006-01-02 15:04:05", s1, loc)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(t2) // 2021-10-20 09:12:13 +0800 CST
}

时间戳与Time转换

时间戳代表当前时间距离1970-01-01 00:00:00的毫秒数

Time转时间戳

package main

import (
	"fmt"
	"time"
)

func main() {
	now := time.Now()
	timestamp := now.Unix()         // 毫秒时间戳
	timestampNano := now.UnixNano() // 纳秒时间戳
	fmt.Println(timestamp)          // 1706153390
	fmt.Println(timestampNano)      // 1706153390764293000
}

时间戳转Time,func Unix(sec int64, nsec int64) Time,第一个参数是毫秒,第二个参数是纳秒

package main

import (
	"fmt"
	"time"
)

func main() {
	milliTimestamp := 1706153390
	nanoTimestamp := 1706153390764293000
	t1 := time.Unix(int64(milliTimestamp), 0)
	t2 := time.Unix(0, int64(nanoTimestamp))

	fmt.Println(t1) // 2024-01-25 11:29:50 +0800 CST
	fmt.Println(t2) // 2024-01-25 11:29:50.764293 +0800 CST
}

时间操作

time.Duration是time包定义的一个类型,它代表两个时间点之间经过的时间,以纳秒为单位。time.Duration表示一段时间间隔,可表示的最长时间段大约290年。

time包中定义的时间间隔类型的常量如下:

type Duration int64

const (
    // 纳秒
    Nanosecond  Duration = 1
    // 微秒
    Microsecond          = 1000 * Nanosecond
    // 毫秒
    Millisecond          = 1000 * Microsecond
    // 秒
    Second               = 1000 * Millisecond
    // 分
    Minute               = 60 * Second
    // 时
    Hour                 = 60 * Minute
)

time.Duration实例提供了方法,可以将该实例换算为float64类型的时、分、秒、毫秒、纳秒

package main

import (
	"fmt"
	"time"
)

func main() {
	d := 6 * time.Hour
	fmt.Printf("%T -- %v\n", d, d) // time.Duration -- 6h0m0s
	h := d.Hours()
	fmt.Printf("%T -- %v\n", h, h) // float64 -- 6
	m := d.Minutes()
	fmt.Printf("%T -- %v\n", m, m) // float64 -- 360
}

ADD

func (t Time) Add(d Duration) Time,计算t+d

package main

import (
	"fmt"
	"time"
)

func main() {
	now := time.Now()
	fmt.Println(now) // 2024-01-25 14:44:20.401889 +0800 CST m=+0.000288709

	// 在now的基础上再加6小时
	later := now.Add(time.Hour * 6)
	fmt.Println(later) // 2024-01-25 20:44:20.401889 +0800 CST m=+21600.000288709

	// 在now的基础上再减6小时
	befor := now.Add(-time.Hour * 6)
	fmt.Println(befor) // 2024-01-25 08:44:20.401889 +0800 CST m=-21599.999711291
}

Sub

func (t Time) Sub(u Time) Duration,计算t-u

package main

import (
	"fmt"
	"time"
)

func main() {
	now := time.Now()
	fmt.Println(now) // 2024-01-25 14:44:20.401889 +0800 CST m=+0.000288709

	// 在now的基础上再加6小时
	later := now.Add(time.Hour * 6)
	fmt.Println(later) // 2024-01-25 20:44:20.401889 +0800 CST m=+21600.000288709

	s := later.Sub(now)
	fmt.Println(s) // 6h0m0s
}

Equal

func (t Time) Equal(u Time) bool,判断两个时间是否相同,会考虑时区的影响,因此不同时区标准的时间也可以正确比较。

Before

func (t Time) Before(u Time) bool,如果t代表的时间点在u之前,返回真;否则返回假。

After

func (t Time) After(u Time) bool,如果t代表的时间点在u之后,返回真;否则返回假。

定时器

Golang原生实现定时器的方法,主要包含如下两种:

实现方法一

通过func NewTicker(d Duration) *Ticker来实现定时器

package main

import (
	"fmt"
	"time"
)

func main() {
	// 两秒执行一次
	t := time.NewTicker(2 * time.Second)
	var tc <-chan time.Time = t.C
	for now := range tc {
		fmt.Println(now)
	}
}

/*
	2024-01-25 14:58:48.028014 +0800 CST m=+2.001407710
	2024-01-25 14:58:50.027334 +0800 CST m=+4.000730126
	2024-01-25 14:58:52.028136 +0800 CST m=+6.001534835
	...
*/

也可以使用Go封装好的time.Tick()方法,对时间间隔d进行了有效性判断

// Tick is a convenience wrapper for NewTicker providing access to the ticking
// channel only. While Tick is useful for clients that have no need to shut down
// the Ticker, be aware that without a way to shut it down the underlying
// Ticker cannot be recovered by the garbage collector; it "leaks".
// Unlike NewTicker, Tick will return nil if d <= 0.
func Tick(d Duration) <-chan Time {
	if d <= 0 {
		return nil
	}
	return NewTicker(d).C
}
package main

import (
	"fmt"
	"time"
)

func main() {
	tc := time.Tick(2 * time.Second)
	for now := range tc {
		fmt.Println(now)
	}
}

/*
	2024-01-25 14:58:48.028014 +0800 CST m=+2.001407710
	2024-01-25 14:58:50.027334 +0800 CST m=+4.000730126
	2024-01-25 14:58:52.028136 +0800 CST m=+6.001534835
	...
*/

实现方法二

可以利用time.Sleep()时线程睡眠,搭配循环来实现

package main

import (
	"fmt"
	"time"
)

func main() {
	for {
		time.Sleep(2 * time.Second)
		fmt.Println(time.Now())
	}
}

/*
	2024-01-25 14:58:48.028014 +0800 CST m=+2.001407710
	2024-01-25 14:58:50.027334 +0800 CST m=+4.000730126
	2024-01-25 14:58:52.028136 +0800 CST m=+6.001534835
	...
*/