Golang packge time
time 包的官方文档
中文
英文
本文章不是对time包文档的重复,旨在加深对time实现的理解上,以上是文档可以进行查看。
time 包中一些官方定义的结构的认识
go针对时间常量的定义:
const (
Nanosecond Duration = 1 //纳秒
Microsecond = 1000 * Nanosecond //微秒
Millisecond = 1000 * Microsecond // 毫秒
Second = 1000 * Millisecond // 秒
Minute = 60 * Second // 分
Hour = 60 * Minute // 时
)
type Weekday int // 定义星期
const (
Sunday Weekday = iota
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
)
type Month int // 定义月份
const (
January Month = 1 + iota
February
March
April
May
June
July
August
September
October
November
December
)
主要的结构体
type Time struct {
// sec gives the number of seconds elapsed since
// January 1, year 1 00:00:00 UTC.
sec int64 // sec表示从公元1年1月1日00:00:00UTC到要表示的整数秒数,
// nsec specifies a non-negative nanosecond
// offset within the second named by Seconds.
// It must be in the range [0, 999999999].
nsec int32 // nsec表示余下的纳秒数,
// 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 // loc表示时区. sec和nsec处理没有歧义的时间值, loc处理偏移量.
}
type Duration int64 // 针对时间长度的定义,单位为纳秒,两个时间点之间经过的纳秒数
// Location代表一个地点,以及该地点所在的时区信息。北京时间可以使用 Asia/Shanghai
type Location struct {
name string
zone []zone
tx []zoneTrans
cacheStart int64
cacheEnd int64
cacheZone *zone
}
针对以上的结构体和类型,go提供了很多方法。
1. time.Time
time.Time
代表一个纳秒精度的时间点。
time.Time
主要的方法有:获取时间点,获取时间相关信息,时间比较,计算和序列化操作。
1.1 获取时间
-
func Now() Time {}
// 当前本地时间 -
func Unix(sec int64, nsec int64) Time {}
// 根据时间戳返回本地时间 -
func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time {}
// 返回指定时间 -
func Parse(layout, value string) (Time, error)
// 根据指定的时间格式,读取时间字符串的时间 -
func ParseInLocation(layout, value string, loc *Location) (Time, error)
// 相比上一个函数,多一个时区的参数
var t time.Time
t = time.Now() // 返回一个本地时间, 返回的类型是一个 time.Time 的一个结构体
fmt.Println("time.Now():", t)
// 根据时间戳返回本地时间 中国的本地时间也就是东八区的区时
t = time.Unix(12342342410, 111111)
fmt.Println("time.Unix: ", t)
// 返回指定时间 把这个确定的时间转为一个时间time.Time结构体类型
t = time.Date(2019, time.Month(2), 20, 1, 30, 30, 1111111, time.Local)
fmt.Println("time.Date: ", t)
// 按照第一参数的格式,读取后面的时间,格式该怎么用参考后面时间序列化
dt, err := time.Parse("2006-01-02 15:04:05", "2018-04-23 12:24:51")
if err != nil {
fmt.Println("读取错误")
}
fmt.Println(dt.Unix(), dt)
1.2 时间格式化
计算机中表示时间使用时间戳的形式来表示,但是这是我们人不能看懂的,所以就需要序列化(也就是用一个我们人能看懂的格式来表示这个时间)。
func (t Time) Format(layout string) string
// 按照指定格式序列化time.Time
Format
函数需要传递一个字符串,这个字符串就是我们需要给出的一个格式,Format
函数会根据我们给定的格式把time.Time类型序列化。
t = time.Now()
timeStr := t.Format("年月日:2006-01-02 时分秒:15:04:05 英文的星期:Mon 英文月份:Jan 数字一个月中的号数:2 时区:-0700 MST")
fmt.Println(timeStr)
timeStr = t.Format("15:04:05 2006/01/02 ")
fmt.Println(timeStr)
比如年份:短年份06,长年份2006,
月份:01,Jan,January
日:02,2,_2
时:15,3,03
分:04, 4
秒:05, 5
时区:-0700 MST
因为都不相等所以通过遍历layout就可以switch case解析出每个区块的意义和在字符串中的位置,这样输入对应格式的时间字符串就可以顺利解析出来。
这样layout也可以自定义,而且顺序任意,只要符合下列每个区块定义的规则即可,代码中的注释就是规则写法,如果要设置要给复杂的格式参考如下:
const (
_ = iota
stdLongMonth = iota + stdNeedDate // "January"
stdMonth // "Jan"
stdNumMonth // "1"
stdZeroMonth // "01"
stdLongWeekDay // "Monday"
stdWeekDay // "Mon"
stdDay // "2"
stdUnderDay // "_2"
stdZeroDay // "02"
stdHour = iota + stdNeedClock // "15"
stdHour12 // "3"
stdZeroHour12 // "03"
stdMinute // "4"
stdZeroMinute // "04"
stdSecond // "5"
stdZeroSecond // "05"
stdLongYear = iota + stdNeedDate // "2006"
stdYear // "06"
stdPM = iota + stdNeedClock // "PM"
stdpm // "pm"
stdTZ = iota // "MST"
stdISO8601TZ // "Z0700" // prints Z for UTC
stdISO8601SecondsTZ // "Z070000"
stdISO8601ShortTZ // "Z07"
stdISO8601ColonTZ // "Z07:00" // prints Z for UTC
stdISO8601ColonSecondsTZ // "Z07:00:00"
stdNumTZ // "-0700" // always numeric
stdNumSecondsTz // "-070000"
stdNumShortTZ // "-07" // always numeric
stdNumColonTZ // "-07:00" // always numeric
stdNumColonSecondsTZ // "-07:00:00"
stdFracSecond0 // ".0", ".00", ... , trailing zeros included
stdFracSecond9 // ".9", ".99", ..., trailing zeros omitted
stdNeedDate = 1 << 8 // need month, day, year
stdNeedClock = 2 << 8 // need hour, minute, second
stdArgShift = 16 // extra argument in high bits, above low stdArgShift
stdMask = 1<<stdArgShift - 1 // mask out argument
)
除了可以自己自定义格式外,go还给了很多标准化的格式
const (
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"
)
-
func (t Time) UTC() Time {}
// 获取指定时间在UTC 时区的时间表示 -
func (t Time) Local() Time {}
// 以本地时区表示 -
func (t Time) In(loc *Location) Time {}
// 给Time设置时区
// 获取指定时间在UTC 时区(零时区)的时间表示
t = time.Now()
t_by_utc := t.UTC()
fmt.Println("'t.UTC': ", t_by_utc)
// 获取本地时间表示
t_by_local := t.Local()
fmt.Println("'t.Local': ", t_by_local)
// 时间在指定时区的表示
t_in := t.In(time.UTC)
fmt.Println("'t.In': ", t_in)
-
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) ISOWeek() (year, week int) {}
// 返回年,星期范围编号 -
func (t Time) Clock() (hour, min, sec int) {}
// 返回时间的时分秒 -
func (t Time) Hour() int {}
// 返回小时
*func (t Time) Minute() int {}
// 分钟 -
func (t Time) Second() int {}
// 秒 -
func (t Time) Nanosecond() int {}
// 纳秒 -
func (t Time) YearDay() int {}
// 一年中对应的天 -
func (t Time) Location() *Location {}
// 时间的时区 -
func (t Time) Zone() (name string, offset int) {}
// 时间所在时区的规范名和想对UTC 时间偏移量 -
func (t Time) Unix() int64 {}
// 时间转为时间戳 -
func (t Time) UnixNano() int64 {}
// 时间转为时间戳(纳秒)
1.3 时间序列化
-
func (t Time) MarshalBinary() ([]byte, error) {}
// 时间序列化 -
func (t Time) UnmarshalBinary(data []byte) error {}
// 反序列化 -
func (t Time) MarshalJSON() ([]byte, error) {}
// 时间序列化 -
func (t *Time) UnmarshalJSON(data []byte) (err error)
// 时间反序列化 -
func (t Time) MarshalText() ([]byte, error) {}
// 时间序列化 -
func (t *Time) UnmarshalText(data []byte) (err error)
// 时间反序列化 -
func (t Time) GobEncode() ([]byte, error) {}
// 时间序列化 -
func (t Time) GobDecode() ([]byte, error) {}
// 时间序列化
b,err := t.MarshalJSON() // 序列化
if err != nil {
log.Println(" MarshalJSON error ")
}
fmt.Println(string(b))
t.AddDate(1,1,1)
t.UnmarshalJSON(b) // 反序列化
fmt.Println(t)
1.4 时间比较与计算
-
func (t Time) IsZero() bool {}
// 是否是零时时间 -
func (t Time) After(u Time) bool {}
// 时间在u 之前 -
func (t Time) Before(u Time) bool {}
// 时间在u 之后 -
func (t Time) Equal(u Time) bool {}
// 时间与u 相同 -
func (t Time) Add(d Duration) Time {}
// 返回t +d 的时间点 -
func (t Time) Sub(u Time) Duration {}
// 返回 t-u -
func (t Time) AddDate(years int, months int, days int) Time {}
//返回增加了给出的年份、月份和天数的时间点Time -
func (t Time) Round(d Duration) Time
// 保留时间,返回距离t最近的时间点 -
func (t Time) Truncate(d Duration) Time
// 在上面的基础上向上取整
t := time.Date(0, 0, 0, 12, 15, 30, 918273645, time.UTC)
round := []time.Duration{
time.Nanosecond,
time.Microsecond,
time.Millisecond,
time.Second,
2 * time.Second,
time.Minute,
10 * time.Minute,
time.Hour,
}
for _, d := range round {
fmt.Printf("t.Round(%6s) = %s\n", d, t.Round(d).Format("15:04:05.999999999"))
}
输出: 对时间进行保留
t.Round( 1ns) = 12:15:30.918273645
t.Round( 1us) = 12:15:30.918274
t.Round( 1ms) = 12:15:30.918
t.Round( 1s) = 12:15:31
t.Round( 2s) = 12:15:30
t.Round( 1m0s) = 12:16:00
t.Round( 10m0s) = 12:20:00
t.Round(1h0m0s) = 12:00:00
time.Duration
time.Duration
表示的是时间段,时间段的定义在文章开头部分
常用的时间段。没有定义一天或超过一天的单元,以避免夏时制的时区切换的混乱。
-
func (d Duration) String() string
// 格式化输出 Duration -
func (d Duration) Nanoseconds() int64
// 将时间段表示为纳秒 -
func (d Duration) Seconds() float64
// 将时间段表示为秒 -
func (d Duration) Minutes() float64
// 将时间段表示为分钟 -
func (d Duration) Hours() float64
// 将时间段表示为小时
// time.Duration 时间段
fmt.Println("time.Duration 时间段")
d := time.Duration(10000000000000)
fmt.Printf("'String: %v', 'Nanoseconds: %v', 'Seconds: %v', 'Minutes: %v', 'Hours: %v'\n",
d.String(), d.Nanoseconds(), d.Seconds(), d.Minutes(), d.Hours())
-
func Since(t Time) Duration
// 返回从t时间到现在时间的长度,等价于time.Now().Sub(t) -
func ParseDuration(s string) (Duration, error)
// 解析一个时间段字符串。一个时间段字符串是一个序列,每个片段包含可选的正负号、十进制数、可选的小数部分和单位后缀,如"300ms"、"-1.5h"、"2h45m"。合法的单位有"ns"、"us"、"µs"、"ms"、"s"、"m"、"h"。
d,err = time.ParseDuration("-1h45m30s")
if err != nil {
log.Println("ParseDuration 解析错误")
}
fmt.Printf("'String: %v', 'Nanoseconds: %v', 'Seconds: %v', 'Minutes: %v', 'Hours: %v'\n",
d.String(), d.Nanoseconds(), d.Seconds(), d.Minutes(), d.Hours())
time.Location
time.Location
的结构在文章开头给出了。
-
func (l *Location) String() string
// 输出时区名 -
func FixedZone(name string, offset int) *Location
// FixedZone 使用给定的地点名name和时间偏移量offset(单位秒)创建并返回一个Location -
func LoadLocation(name string) (*Location, error)
// LoadLocation 使用给定的名字创建Location
var local *time.Location
local, ok := time.LoadLocation("Asia/Shanghai")
fmt.Printf("%v, %T, %v\n", local, local, ok)
local, ok = time.LoadLocation("Asia/Chongqing")
fmt.Printf("%v, %T, %v\n", local, local, ok)
var cstZone = time.FixedZone("CST", 8*3600) // 东八
fmt.Println("SH : ", time.Now().In(cstZone).Format("2006-01-02 15:04:05"))
time.Sleep() 常用
-
func Sleep(d Duration)
// Sleep阻塞当前go程至少d代表的时间段。d<=0时,Sleep会立刻返回,
查看 runtime/time.go
文件中的timeSleep
可知,Sleep
的是通过 Timer
实现的,把当前 goroutine
作为 arg
参数(getg())
。
time.Timer time.Ticker
参考我的另一篇笔记:Golang time.Timer and time.Ticker
参考
Go 标准库介绍二: time
深入理解GO时间处理(time.Time)
golang包time用法详解
Time包