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包

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • 原文链接 http://ironxu.com/747 介绍Go 标准库 time 常用导出函数,结构体及其方法。 ...
    好刚编程阅读 16,951评论 2 11
  • 本章就来学习时间相关的所有操作 1.延迟d秒后返回通过信道返回时间值 func After(d Duration)...
    酷走天涯阅读 1,246评论 0 2
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,733评论 0 38
  • 类型 time.Time{} 时间类型,包含了秒和纳秒以及Location time.Month() type M...
    吃猫的鱼0阅读 31,751评论 0 4
  • 有些傻话,不但是要背着别人说,还得背着自己说。让自己听见了也怪难为情的。譬如说,我爱你,我一辈子都爱你。 今天收到...
    徐灵阅读 1,336评论 6 24