Go package——time篇

golang关于时间操作的标准包

整理一下Go语言中time包中的函数

Go 版本: 1.19.1

Time数据结构

时间点time.Time

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
type Time struct {
	// wall and ext encode the wall time seconds, wall time nanoseconds,
	// and optional monotonic clock reading in nanoseconds.
	//
	// From high to low bit position, wall encodes a 1-bit flag (hasMonotonic),
	// a 33-bit seconds field, and a 30-bit wall time nanoseconds field.
	// The nanoseconds field is in the range [0, 999999999].
	// If the hasMonotonic bit is 0, then the 33-bit field must be zero
	// and the full signed 64-bit wall seconds since Jan 1 year 1 is stored in ext.
	// If the hasMonotonic bit is 1, then the 33-bit field holds a 33-bit
	// unsigned wall seconds since Jan 1 year 1885, and ext holds a
	// signed 64-bit monotonic clock reading, nanoseconds since process start.
	wall uint64
	ext  int64

	// loc specifies the Location that should be used to
	// determine the minute, hour, month, day, and year
	// that correspond to this Time.
	// The nil location means UTC.
	// All UTC times are represented with loc==nil, never loc==&utcLoc.
	loc *Location
}

时间段time.Duration

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
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
)

Duration函数将两个瞬间之间的经过时间表示为 int64 纳秒计数。该表示将最大可表示持续时间限制为大约 290 年。

Time函数

时间创建

1
func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time

Date函数通过传入参数创建时间

时间比较

1
2
3
func (t Time) After(u Time) bool
func (t Time) Before(u Time) bool
func (t Time) Equal(u Time) bool

AfterBeforeEqual函数分别判断时间t是否在时间u之后之前相等

时间判断

零值判断

1
func (t Time) IsZero() bool

在Go中,time.Time的零值为January 1, year 1, 00:00:00 UTC

DST判断

1
func (t Time) IsDST() bool

IsDST判断是否为DST(夏令时)时间

时间计算

1
2
func (t Time) Add(d Duration) Time
func (t Time) Sub(u Time) Duration

AddSub函数为时间的增加与减少的操作。

1
2
func Since(t Time) Duration
func Until(t Time) Duration

Since函数返回从时间点t到现在的时间段,为time.Now().Sub(t)的简写。
Until函数返回现在到时间点t的时间段,为t.Sub(time.Now())的简写。

1
func (t Time) AddDate(years int, months int, days int) Time

AddDate函数计算日期变更

时间信息返回

时间点time.Time信息

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
func (t Time) Date() (year int, month Month, day int)
func (t Time) Year() int
func (t Time) Month() Month 
func (t Time) Day() int
func (t Time) Weekday() Weekday

func (t Time) Clock() (hour, min, sec int)
func (t Time) Hour()
func (t Time) Minute() int
func (t Time) Second() int
func (t Time) Nanosecond() int

DateYearMonthDayWeekday分别返回时间的日期星期
ClockHourMinuteSecondNanosecond分别返回时间的时刻小时分钟纳秒偏移量

1
2
func (t Time) ISOWeek() (year, week int)
func (t Time) YearDay() int

ISOWeek函数返回时间的ISO 8601的年份与星期数,其中星期数的范围为1~53。其中第 n 年的1月1日到1月3日可能属于第 n-1 年的第52或53周,而12月29日到12月31日可能属于第 n+1 年的第1周。
YearDay函数返回当前年份的天数,其中非闰年的范围为 [1,365],闰年的范围为 [1,366]

时间段time.Duration信息

1
2
3
4
5
6
7
func (d Duration) Nanoseconds() int64
func (d Duration) Microseconds() int64
func (d Duration) Milliseconds() int64

func (d Duration) Seconds() float64
func (d Duration) Minutes() float64
func (d Duration) Hours() float64

NanosecondsMicrosecondsMilliseconds函数分别返回时间段的毫秒微秒纳秒int64形式
SecondsMinutesHours函数分别返回时间段的秒数分钟数小时数的浮点形式

1
func (d Duration) Abs() Duration

Abs函数返回时间段的绝对值 (注:1.19及以上

时区Timezone信息

1
2
3
func (t Time) Location() *Location
func (t Time) Zone() (name string, offset int)
func (t Time) ZoneBounds() (start, end Time)

Location函数返回时间的所在时区。
Zone函数返回时区的名字(例如:CET)与UTC偏移的秒数 ZoneBounds函数返回在给定时间内有效的时区的开始和结束时间。它可以在一个循环中用来列举一个给定地点的所有已知的时区转换情况。啥意思,我不到啊注:1.19及以上

各时区时间Time信息

1
2
3
4
func Now() Time
func (t Time) UTC() Time
func (t Time) Local() Time
func (t Time) In(loc *Location) Time

Now函数返回当前时间
UTC函数返回UTC格式时间
Local函数返回当地格式时间
In函数返回在loc时区的时间

地区Location返回

1
2
func FixedZone(name string, offset int) *Location
func LoadLocation(name string) (*Location, error)

FixedZone函数返回一个始终使用给定区域名称和偏移量(UTC以东的秒数)的Location。例:

1
2
3
4
5
6
	loc := time.FixedZone("UTC-8", -8*60*60)
	t := time.Date(2009, time.November, 10, 23, 0, 0, 0, loc)
	fmt.Println("The time is:", t.Format(time.RFC822))

	//Output:
	//The time is: 10 Nov 09 23:00 UTC-8

LoadLocation函数返回给定名称的位置,如果参数为空或UTC,则返回UTC

如果参数为Local,则返回local

如果参数在IANA时区数据库中,则返回相应地区的位置,例如:America/New_York

例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
	location, err := time.LoadLocation("America/Los_Angeles")
	if err != nil {
		panic(err)
	}

	timeInUTC := time.Date(2018, 8, 30, 12, 0, 0, 0, time.UTC)
	fmt.Println(timeInUTC.In(location))

	//Output:
	//2018-08-30 05:00:00 -0700 PDT

时间戳Unix信息

1
2
3
4
func (t Time) Unix() int64
func (t Time) UnixMilli() int64
func (t Time) UnixMicro() int64
func (t Time) UnixNano() int64

Unix函数返回时间戳秒数(从January 1, 1970 UTC到时间t
UnixMilli函数返回时间戳毫秒数(从January 1, 1970 UTC到时间t)(1970年之前或之后超过2.92亿年的日期)
UnixMicro函数返回时间戳微秒数(从January 1, 1970 UTC到时间t)(-290307年之前或294246年之后的日期)
UnixNano函数返回时间戳纳秒数(从January 1, 1970 UTC到时间t)(1678年之前或2262年之后的日期)

1
2
3
func Unix(sec int64, nsec int64) Time
func UnixMilli(msec int64) Time
func UnixMicro(usec int64) Time

Unix函数返回自1970年1月1日UTC以来与给定Unix时间(秒和纳秒)相对应的本地时间。传递超出范围[0,999999999]的nsec是有效的。并非所有秒值都有相应的时间值。
UnixMilliUnixMicro分别输入毫秒与微秒同时返回时间

时间字符串String输出

时间段String

1
func (d Duration) String() string

以“72h3m0.5s”的形式返回一个表示持续时间的字符串。
小于1s的时间段使用更小的单位(毫秒、微秒或纳秒)。
零持续时间格式为0s。

月份、日期String

1
2
func (m Month) String() string
func (d Weekday) String() string

日期、星期转为string类型

时间编解码

二进制、文本编解码

1
2
3
4
func (t Time) MarshalBinary() ([]byte, error)
func (t *Time) UnmarshalBinary(data []byte) error
func (t Time) MarshalText() ([]byte, error)
func (t *Time) UnmarshalText(data []byte)

MarshalBinary函数将时间序列化为二进制
UnmarshalBinary函数将二进制反序列化为时间t中
MarshalText函数将时间序列化为[]byte切片
UnmarshalText函数将[]byte切片反序列化为时间t

其他类型的编解码

1
2
3
4
func (t Time) GobEncode() ([]byte, error)
func (t *Time) GobDecode(data []byte) error
func (t Time) MarshalJSON() ([]byte, error)
func (t *Time) UnmarshalJSON(data []byte) error

God与JSON类型的编解码,将在GO2中废弃

时间截断

1
2
3
4
5
func (t Time) Truncate(d Duration) Time
func (d Duration) Truncate(m Duration) Duration

func (t Time) Round(d Duration) Time
func (d Duration) Round(m Duration) Duration

Truncate函数返回将时间t/时间段d向零舍入到时间段m的倍数的结果。如果 m <= 0,返回直接返回d
Round函数返回四舍五入到时间段m的倍数的结果。如果结果超过 time.Duration 可以存储的最大/最小值,Round函数返回最大/最小段时间。如果 m <= 0,Round函数返回 d 不变。

时间格式化输出

格式化字符串layout

以下是时间字符串的元素:

  • 年:2006 06
  • 月:Jan January 01 1
  • 星期:Mon Monday
  • 日:2 _2 02
  • 年份的天数:__2 002
  • 小时:15 3 03 (PM or AM)
  • 分:4 04
  • 秒:5 05
  • AM/PM:PM

其中时区偏移格式为:

  • “-0700” ±hhmm

  • “-07:00” ±hh:mm

  • “-07” ±hh

  • “-070000” ±hhmmss

  • “-07:00:00” ±hh:mm:ss

将格式中的符号替换为Z将触发ISO 8601打印Z的行为,而不是UTC区域的偏移:

  • “Z0700” Z or ±hhmm
  • “Z07:00” Z or ±hh:mm
  • “Z07” Z or ±hh
  • “Z070000” Z or ±hhmmss
  • “Z07:00:00” Z or ±hh:mm:ss

以下是预设的时间格式:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
	Layout      = "01/02 03:04:05PM '06 -0700" // The reference time, in numerical order.
	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"

时间格式化

1
2
func (t Time) Format(layout string) string
func (t Time) AppendFormat(b []byte, layout string) []byte

Format函数以传入的layout字符串对时间进行格式化输出

AppendFormat函数与Format类似,但将文本append到b中,并返回拓展的buffer,例:

1
2
3
4
5
6
7
8
t := time.Date(2017, time.November, 4, 11, 0, 0, 0, time.UTC)
text := []byte("Time: ")

text = t.AppendFormat(text, time.Kitchen)
fmt.Println(string(text))

//Output:
//Time: 11:00AM

时间转字符串

1
2
func (t Time) String() string
func (t Time) GoString() string

String函数字符串返回 "2006-01-02 15:04:05.999999999 -0700 MST"字符串格式化的时间。如果时间具有monotonic clock读数,则返回的字符串包括一个最终字段“m=±”,其中value是格式化为十进制秒数的单调时钟读数。返回的字符串用于调试;要获得稳定的序列化表示形式,请使用t.MarshalText、t.MarshallBinary或带有显式格式字符串的t.Format。

Go 中时间格式化字符串为: 2006-01-02 15:04:05.999999999 -0700 MST

GoString函数实现了 fmt.GoStringer,用于Go源码的打印输出

时间解析

1
2
3
4
func Parse(layout, value string) (Time, error)
func ParseInLocation(layout, value string, loc *Location) (Time, error)

func ParseDuration(s string) (Duration, error)

Parse函数第一个参数为格式化字符串layout,第二个参数为可以解析的value值。

ParseInLocationParse类似,但在两个重要方面有所不同。首先,在没有时区信息的情况下,Parse将时间解释为UTC,而ParseInLocation将时间解析为给定位置中的时间。其次,当给定区域偏移或缩写时,Parse会尝试将其与Local位置匹配,而ParseInLocation使用给定的位置。

ParseDuration解析时间段字符串。时间段字符串可能是有符号的十进制数字序列,每个数字都有可选的分数和单位后缀,例如“300ms”、“-1.5h”或“2h45m”。有效时间单位为“ns”、“us”(或“µs”)、“ms”、“s”、“m”、“h”。

计时器

Ticker数据结构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
type Ticker struct {
	C <-chan Time // The channel on which the ticks are delivered.
	r runtimeTimer
}

type runtimeTimer struct {
	pp       uintptr
	when     int64
	period   int64
	f        func(any, uintptr) // NOTE: must not be closure
	arg      any
	seq      uintptr
	nextwhen int64
	status   uint32
}

Ticker函数

新建Ticker

1
2
3
func NewTicker(d Duration) *Ticker

func Tick(d Duration) <-chan Time

Tick函数是NewTicker的封装,它只提供Time 的channel。虽然Tick对于不需要关闭Ticker的客户端很有用,但请注意,如果没有关闭Ticker的方法,垃圾回收器就无法恢复底层Ticker

Ticker停止

1
func (t *Ticker) Stop()

Ticker重置

1
func (t *Ticker) Reset(d Duration)

Reset函数将Ticker重置为新的时间间隔d

定时器

Timer数据结构

1
2
3
4
type Timer struct {
	C <-chan Time
	r runtimeTimer
}

Timer函数

新建Timer

1
2
3
4
func NewTimer(d Duration) *Timer

func After(d Duration) <-chan Time
func AfterFunc(d Duration, f func()) *Timer

After函数等待持续时间过去后,在返回的通道上发送当前时间,等效于NewTimer(d).C。如果注重效率,改用NewTimer函数,并在不再需要计时器时调用Timer.Stop

AfterFunc等待持续时间过去,然后在自己的goroutine中调用函数f。它返回一个计时器,可用于使用Stop函数取消调用

Timer停止

1
func (t *Timer) Stop()

Timer重置

1
func (t *Timer) Reset(d Duration) bool

参考

https://blog.codeminer42.com/the-monotonic-clock-and-why-you-should-care-about-it/

Licensed under CC BY-NC-SA 4.0