time

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

Constants

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
    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
    RFC3339     = "2006-01-02T15:04:05Z07:00"
    RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
    Kitchen     = "3:04PM"
    // 方便的时间戳
    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"
)

这些预定义的版式用于Time.Format和Time.Parse函数。用在版式中的参考时间是:

Mon Jan 2 15:04:05 MST 2006

对应的Unix时间是1136239445。因为MST的时区是GMT-0700,参考时间也可以表示为如下:

01/02 03:04:05PM '06 -0700

要定义你自己的格式,写下该参考时间应用于你的格式的情况;例子请参见ANSIC、StampMicro或Kitchen等常数的值。该模型是为了演示参考时间的格式化效果,如此一来Format和Parse方法可以将相同的转换规则用于一个普通的时间值。

在格式字符串中,用前置的'0'表示一个可以被可以被数字替换的'0'(如果它后面的数字有两位);使用下划线表示一个可以被数字替换的空格(如果它后面的数字有两位);以便兼容Unix定长时间格式。

小数点后跟0到多个'0',表示秒数的小数部分,输出时会生成和'0'一样多的小数位;小数点后跟0到多个'9',表示秒数的小数部分,输出时会生成和'9'一样多的小数位但会将拖尾的'0'去掉。(只有)解析时,输入可以在秒字段后面紧跟一个小数部分,即使格式字符串里没有指明该部分。此时,小数点及其后全部的数字都会成为秒的小数部分。

数字表示的时区格式如下:

-0700  ±hhmm
-07:00 ±hh:mm

将格式字符串中的负号替换为Z会触发ISO 8601行为(当时区是UTC时,输出Z而不是时区偏移量),这样:

Z0700  Z or ±hhmm
Z07:00 Z or ±hh:mm

type ParseError

type ParseError struct {
    Layout     string
    Value      string
    LayoutElem string
    ValueElem  string
    Message    string
}

ParseError描述解析时间字符串时出现的错误。

func (*ParseError) Error

func (e *ParseError) Error() string

Error返回ParseError的字符串表示。

type Weekday

type Weekday int

Weekday代表一周的某一天。

const (
    Sunday Weekday = iota
    Monday
    Tuesday
    Wednesday
    Thursday
    Friday
    Saturday
)

func (Weekday) String

func (d Weekday) String() string

String返回该日(周几)的英文名("Sunday"、"Monday",……)

type Month

type Month int

Month代表一年的某个月。

const (
    January Month = 1 + iota
    February
    March
    April
    May
    June
    July
    August
    September
    October
    November
    December
)
func main() {
   _, month, day := time.Now().Date()
   if month == time.November && day == 10 {
      fmt.Println("Happy Go day!")
   }
}

func (Month) String

func (m Month) String() string

String返回月份的英文名("January","February",……)

type Location

type Location struct {
    name string
    zone []zone
    tx   []zoneTrans
    extend string
    cacheStart int64
    cacheEnd   int64
    cacheZone  *zone
}

Location代表一个(关联到某个时间点的)地点,以及该地点所在的时区。

var Local *Location = &localLoc

Local代表系统本地,对应本地时区。

var UTC *Location = &utcLoc

UTC代表通用协调时间,对应零时区。

func LoadLocation

func LoadLocation(name string) (*Location, error)

LoadLocation返回使用给定的名字创建的Location。

如果name是""或"UTC",返回UTC;如果name是"Local",返回Local;否则name应该是IANA时区数据库里有记录的地点名(该数据库记录了地点和对应的时区),如"America/New_York"。

LoadLocation函数需要的时区数据库可能不是所有系统都提供,特别是非Unix系统。此时LoadLocation会查找环境变量ZONEINFO指定目录或解压该变量指定的zip文件(如果有该环境变量);然后查找Unix系统的惯例时区数据安装位置,最后查找$GOROOT/lib/time/zoneinfo.zip。

func FixedZone

func FixedZone(name string, offset int) *Location

FixedZone使用给定的地点名name和时间偏移量offset(单位秒)创建并返回一个Location

func (*Location) String

func (l *Location) String() string

String返回对时区信息的描述,返回值绑定为LoadLocation或FixedZone函数创建l时的name参数。

type Time

type Time struct {
    wall uint64
    ext  int64
    loc *Location
}

Time代表一个纳秒精度的时间点。

程序中应使用Time类型值来保存和传递时间,而不能用指针。就是说,表示时间的变量和字段,应为time.Time类型,而不是*time.Time.类型。一个Time类型值可以被多个go程同时使用。时间点可以使用Before、After和Equal方法进行比较。Sub方法让两个时间点相减,生成一个Duration类型值(代表时间段)。Add方法给一个时间点加上一个时间段,生成一个新的Time类型时间点。

Time零值代表时间点January 1, year 1, 00:00:00.000000000 UTC。因为本时间点一般不会出现在使用中,IsZero方法提供了检验时间是否显式初始化的一个简单途径。

每一个时间都具有一个地点信息(及对应地点的时区信息),当计算时间的表示格式时,如Format、Hour和Year等方法,都会考虑该信息。Local、UTC和In方法返回一个指定时区(但指向同一时间点)的Time。修改地点/时区信息只是会改变其表示;不会修改被表示的时间点,因此也不会影响其计算。

func main() {
   t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
   fmt.Printf("Go launched at %s\n", t.Local())
}

func Date

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

Date返回一个时区为loc、当地时间为:

year-month-day hour:min:sec + nsec nanoseconds

month、day、hour、min、sec和nsec的值可能会超出它们的正常范围,在转换前函数会自动将之规范化。如October 32被修正为November 1。

夏时制的时区切换会跳过或重复时间。如,在美国,March 13, 2011 2:15am从来不会出现,而November 6, 2011 1:15am 会出现两次。此时,时区的选择和时间是没有良好定义的。Date会返回在时区切换的两个时区其中一个时区

正确的时间,但本函数不会保证在哪一个时区正确。

如果loc为nil会panic。

func Now

func Now() Time

Now返回当前本地时间。

func main() {
   const longForm = "Jan 2, 2006 at 3:04pm (MST)"
   t, _ := time.Parse(longForm, "Feb 3, 2013 at 7:54pm (PST)")
   fmt.Println(t)
   const shortForm = "2006-Jan-02"
   t, _ = time.Parse(shortForm, "2013-Feb-03")
   fmt.Println(t)
}

func Parse

func Parse(layout, value string) (Time, error)
Mon Jan 2 15:04:05 -0700 MST 2006

在输入格式下的字符串表示,作为输入的格式的示例。同样的格式规则会被用于输入字符串。

预定义的ANSIC、UnixDate、RFC3339和其他版式描述了参考时间的标准或便捷表示。要获得更多参考时间的定义和格式,参见本包的ANSIC和其他版式常量。

value中漏掉的元素会被视为0;如果不能是0,会被视为1。因此,解析"3:04pm"会返回对应时间点:Jan 1, year 0, 15:04:00 UTC的Time(注意因为year为0,该时间在Time零值之前)。年份必须在0000..9999范围内。周几会被检查其语法,但是会被忽略。

如果缺少表示时区的信息,Parse会将时区设置为UTC。

当解析具有时区偏移量的时间字符串时,如果该时区偏移量和本地时区相同,Parse会在返回值中将Location设置为本地和本地时区。否则,它会将Location设置为一个虚构的具有该时区偏移量的值。

当解析具有时区缩写的时间字符串时,如果该时区缩写具有已定义的时间偏移量,会使用该偏移量。如果时区缩写是"UTC",会将该时间视为UTC时间,不考虑Location。如果时区缩写是未知的,Parse会将Location设置为一个虚构的地点为时区缩写,时间偏移量为0的值。这种做法是为了让一个时间可以在同一版式下不丢失信息的被解析和重新格式化;但字符串表示和具体表示的时间点会因为实际时区偏移量而不同。为了避免这些问题,请使用数字表示的时区偏移量,或者使用ParseInLocation函数。

func main() {
   loc, _ := time.LoadLocation("Europe/Berlin")
   const longForm = "Jan 2, 2006 at 3:04pm (MST)"
   t, _ := time.ParseInLocation(longForm, "Jul 9, 2012 at 5:02am (CEST)", loc)
   fmt.Println(t)
   // Note: without explicit zone, returns time in given location.
   const shortForm = "2006-Jan-02"
   t, _ = time.ParseInLocation(shortForm, "2012-Jul-09", loc)
   fmt.Println(t)
}

func ParseInLocation

func ParseInLocation(layout, value string, loc *Location) (Time, error)

ParseInLocation类似Parse但有两个重要的不同之处。第一,当缺少时区信息时,Parse将时间解释为UTC时间,而ParseInLocation将返回值的Location设置为loc;第二,当时间字符串提供了时区偏移量信息时,Parse会尝试去匹配本地时区,而ParseInLocation会去匹配loc。

func Unix

func Unix(sec int64, nsec int64) Time
Unix创建一个本地时间,对应sec和nsec表示的Unix时间(从January 1, 1970 UTC至该时间的秒数和纳秒数)。
nsec的值在[0, 999999999]范围外是合法的。

func (Time) Location

func (t Time) Location() *Location

Location返回t的地点和时区信息。

func (Time) Zone

func (t Time) Zone() (name string, offset int)

Zone计算t所在的时区,返回该时区的规范名(如"CET")和该时区相对于UTC的时间偏移量(单位秒)。

func (Time) IsZero

func (t Time) IsZero() bool

IsZero报告t是否代表Time零值的时间点,January 1, year 1, 00:00:00 UTC。

func (Time) Local

func (t Time) Local() Time

Local返回采用本地和本地时区,但指向同一时间点的Time。

func (Time) UTC

func (t Time) UTC() Time

UTC返回采用UTC和零时区,但指向同一时间点的Time。

func (Time) In

func (t Time) In(loc *Location) Time

In返回采用loc指定的地点和时区,但指向同一时间点的Time。如果loc为nil会panic。

func (Time) Unix

func (t Time) Unix() int64

Unix将t表示为Unix时间,即从时间点January 1, 1970 UTC到时间点t所经过的时间(单位秒)。

func (Time) UnixNano

func (t Time) UnixNano() int64

UnixNano将t表示为Unix时间,即从时间点January 1, 1970 UTC到时间点t所经过的时间(单位纳秒)。如果纳秒为单位的unix时间超出了int64能表示的范围,结果是未定义的。注意这就意味着Time零值调用UnixNano方法的话,结果是未定义的。

func (Time) Equal

func (t Time) Equal(u Time) bool

判断两个时间是否相同,会考虑时区的影响,因此不同时区标准的时间也可以正确比较。本方法和用t==u不同,这种方法还会比较地点和时区信息。

func (Time) Before

func (t Time) Before(u Time) bool

如果t代表的时间点在u之前,返回真;否则返回假。

func (Time) After

func (t Time) After(u Time) bool

如果t代表的时间点在u之后,返回真;否则返回假。

func (Time) Date

func (t Time) Date() (year int, month Month, day int)

返回时间点t对应的年、月、日。

func (Time) Clock

func (t Time) Clock() (hour, min, sec int)

返回t对应的那一天的时、分、秒。

func (Time) Year

func (t Time) Year() int

返回时间点t对应的年份。

func (Time) Month

func (t Time) Month() Month

返回时间点t对应那一年的第几月。

func (Time) ISOWeek

func (t Time) ISOWeek() (year, week int)

返回时间点t对应的ISO 9601标准下的年份和星期编号。星期编号范围[1,53],1月1号到1月3号可能属于上一年的最后一周,12月29号到12月31号可能属于下一年的第一周。

func (Time) YearDay

func (t Time) YearDay() int

返回时间点t对应的那一年的第几天,平年的返回值范围[1,365],闰年[1,366]。

func (Time) Day

func (t Time) Day() int

返回时间点t对应那一月的第几日。

func (Time) Weekday

func (t Time) Weekday() Weekday

返回时间点t对应的那一周的周几。

func (Time) Hour

func (t Time) Hour() int

返回t对应的那一天的第几小时,范围[0, 23]。

func (Time) Minute

func (t Time) Minute() int

返回t对应的那一小时的第几分种,范围[0, 59]。

func (Time) Second

func (t Time) Second() int

返回t对应的那一分钟的第几秒,范围[0, 59]。

func (Time) Nanosecond

func (t Time) Nanosecond() int

返回t对应的那一秒内的纳秒偏移量,范围[0, 999999999]。

func (Time) Add

func (t Time) Add(d Duration) Time

Add返回时间点t+d。

func (Time) AddDate

func (t Time) AddDate(years int, months int, days int) Time
AddDate返回增加了给出的年份、月份和天数的时间点Time。例如,时间点January 1, 2011调用AddDate(-1, 2, 3)会返回March 4, 2010。
AddDate会将结果规范化,类似Date函数的做法。因此,举个例子,给时间点October 31添加一个月,会生成时间点December 1。(从时间点November 31规范化而来)

func (Time) Sub

func (t Time) Sub(u Time) Duration

返回一个时间段t-u。如果结果超出了Duration可以表示的最大值/最小值,将返回最大值/最小值。要获取时间点t-d(d为Duration),可以使用t.Add(-d)。

func (Time) Round

func (t Time) Round(d Duration) Time

返回距离t最近的时间点,该时间点应该满足从Time零值到该时间点的时间段能整除d;如果有两个满足要求的时间点,距离t相同,会向上舍入;如果d <= 0,会返回t的拷贝。

func main() {
   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"))
   }
}

func (Time) Truncate

func (t Time) Truncate(d Duration) Time

类似Round,但是返回的是最接近但早于t的时间点;如果d <= 0,会返回t的拷贝。

func main() {
   t, _ := time.Parse("2006 Jan 02 15:04:05", "2012 Dec 07 12:15:30.918273645")
   trunc := []time.Duration{
      time.Nanosecond,
      time.Microsecond,
      time.Millisecond,
      time.Second,
      2 * time.Second,
      time.Minute,
      10 * time.Minute,
      time.Hour,
   }
   for _, d := range trunc {
      fmt.Printf("t.Truncate(%6s) = %s\n", d, t.Truncate(d).Format("15:04:05.999999999"))
   }
}

func (Time) Format

func (t Time) Format(layout string) string
Mon Jan 2 15:04:05 -0700 MST 2006

格式化后的字符串表示,它作为期望输出的例子。同样的格式规则会被用于格式化时间。

预定义的ANSIC、UnixDate、RFC3339和其他版式描述了参考时间的标准或便捷表示。要获得更多参考时间的定义和格式,参见本包的ANSIC和其他版式常量。

func main() {
   // layout shows by example how the reference time should be represented.
   const layout = "Jan 2, 2006 at 3:04pm (MST)"
   t := time.Date(2009, time.November, 10, 15, 0, 0, 0, time.Local)
   fmt.Println(t.Format(layout))
   fmt.Println(t.UTC().Format(layout))
}

func (Time) String

func (t Time) String() string

String返回采用如下格式字符串的格式化时间。

"2006-01-02 15:04:05.999999999 -0700 MST"

func (Time) GobEncode

func (t Time) GobEncode() ([]byte, error)

GobEncode实现了gob.GobEncoder接口。

func (*Time) GobDecode

func (t *Time) GobDecode(data []byte) error

GobEncode实现了gob.GobDecoder接口。

func (Time) MarshalBinary

func (t Time) MarshalBinary() ([]byte, error)

MarshalBinary实现了encoding.BinaryMarshaler接口。

func (*Time) UnmarshalBinary

func (t *Time) UnmarshalBinary(data []byte) error

UnmarshalBinary实现了encoding.BinaryUnmarshaler接口。

func (Time) MarshalJSON

func (t Time) MarshalJSON() ([]byte, error)

MarshalJSON实现了json.Marshaler接口。返回值是用双引号括起来的采用 RFC 3339 格式进行格式化的时间表示,如果需要会提供小于秒的精度。

func (*Time) UnmarshalJSON

func (t *Time) UnmarshalJSON(data []byte) (err error)

UnmarshalJSON实现了json.Unmarshaler接口。时间被期望是双引号括起来的 RFC 3339 格式。

func (Time) MarshalText

func (t Time) MarshalText() ([]byte, error)

MarshalText实现了encoding.TextMarshaler接口。返回值是采用 RFC 3339 格式进行格式化的时间表示,如果需要会提供小于秒的精度。

func (*Time) UnmarshalText

func (t *Time) UnmarshalText(data []byte) (err error)

UnmarshalText实现了encoding.TextUnmarshaler接口。时间被期望采用 RFC 3339 格式。

type Duration

type Duration int64

Duration类型代表两个时间点之间经过的时间,以纳秒为单位。可表示的最长时间段大约290年。

const (
    Nanosecond  Duration = 1
    Microsecond          = 1000 * Nanosecond
    Millisecond          = 1000 * Microsecond
    Second               = 1000 * Millisecond
    Minute               = 60 * Second
    Hour                 = 60 * Minute
)

常用的时间段。没有定义一天或超过一天的单元,以避免夏时制的时区切换的混乱。

要将Duration类型值表示为某时间单元的个数,用除法:

second := time.Second
fmt.Print(int64(second/time.Millisecond)) // prints 1000

要将整数个某时间单元表示为Duration类型值,用乘法:

seconds := 10
fmt.Print(time.Duration(seconds)*time.Second) // prints 10s

func ParseDuration

func ParseDuration(s string) (Duration, error)

ParseDuration解析一个时间段字符串。一个时间段字符串是一个序列,每个片段包含可选的正负号、十进制数、可选的小数部分和单位后缀,如"300ms"、"-1.5h"、"2h45m"。合法的单位有"ns"、"us" /"µs"、"ms"、"s"、"m"、"h"。

func Since

func Since(t Time) Duration

Since返回从t到现在经过的时间,等价于time.Now().Sub(t)。

func (Duration) Hours

func (d Duration) Hours() float64

Hours将时间段表示为float64类型的小时数。

func (Duration) Minutes

func (d Duration) Minutes() float64

Hours将时间段表示为float64类型的分钟数。

func (Duration) Seconds

func (d Duration) Seconds() float64

Hours将时间段表示为float64类型的秒数。

func (Duration) Nanoseconds

func (d Duration) Nanoseconds() int64

Hours将时间段表示为int64类型的纳秒数,等价于int64(d)。

func (Duration) String

func (d Duration) String() string

返回时间段采用"72h3m0.5s"格式的字符串表示。最前面可以有符号,数字+单位为一个单元,开始部分的0值单元会被省略;如果时间段<1s,会使用"ms"、"us"、"ns"来保证第一个单元的数字不是0;如果时间段为0,会返回"0"。

type Timer

type Timer struct {
    C <-chan Time
    // 内含隐藏或非导出字段
}

Timer类型代表单次时间事件。当Timer到期时,当时的时间会被发送给C,除非Timer是被AfterFunc函数创建的。

func NewTimer

func NewTimer(d Duration) *Timer

NewTimer创建一个Timer,它会在最少过去时间段d后到期,向其自身的C字段发送当时的时间。

func AfterFunc

func AfterFunc(d Duration, f func()) *Timer

AfterFunc另起一个go程等待时间段d过去,然后调用f。它返回一个Timer,可以通过调用其Stop方法来取消等待和对f的调用。

func (*Timer) Reset

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

Reset使t重新开始计时,(本方法返回后再)等待时间段d过去后到期。如果调用时t还在等待中会返回真;如果t已经到期或者被停止了会返回假。

func (*Timer) Stop

func (t *Timer) Stop() bool

Stop停止Timer的执行。如果停止了t会返回真;如果t已经被停止或者过期了会返回假。Stop不会关闭通道t.C,以避免从该通道的读取不正确的成功。

type Ticker

type Ticker struct {
    C <-chan Time // 周期性传递时间信息的通道
    // 内含隐藏或非导出字段
}

Ticker保管一个通道,并每隔一段时间向其传递"tick"。

func NewTicker

func NewTicker(d Duration) *Ticker

NewTicker返回一个新的Ticker,该Ticker包含一个通道字段,并会每隔时间段d就向该通道发送当时的时间。它会调整时间间隔或者丢弃tick信息以适应反应慢的接收者。如果d<=0会panic。关闭该Ticker可以释放相关资源。

func (*Ticker) Stop

func (t *Ticker) Stop()

Stop关闭一个Ticker。在关闭后,将不会发送更多的tick信息。Stop不会关闭通道t.C,以避免从该通道的读取不正确的成功。

func Sleep

func Sleep(d Duration)

Sleep阻塞当前go程至少d代表的时间段。d<=0时,Sleep会立刻返回。

func After

func After(d Duration) <-chan Time

After会在另一线程经过时间段d后向返回值发送当时的时间。等价于NewTimer(d).C。

select {
case m := <-c:
    handle(m)
case <-time.After(5 * time.Minute):
    fmt.Println("timed out")
}

func Tick

func Tick(d Duration) <-chan Time

Tick是NewTicker的封装,只提供对Ticker的通道的访问。如果不需要关闭Ticker,本函数就很方便。

c := time.Tick(1 * time.Minute)
for now := range c {
    fmt.Printf("%v %s\n", now, statusUpdate())
}