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

IANA

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包

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务