time

Month

Monthint值,1到12分别表示12个月:

type Month int

const (
    January Month = 1 + iota
    February
    March
    April
    May
    June
    July
    August
    September
    October
    November
    December
)

Weekday

Weekdayint值,0到6分别表示周日到周六:

type Weekday int

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

Duration

Duration表示时间间隔,为int64类型,单位为纳秒。相关常量有:

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

例如:

d := time.Duration(1*time.Hour + 2*time.Minute + 3*time.Second + 45678)
fmt.Println(d.String())      // 1h2m3.000045678s
fmt.Println(d.Hours())       // 1.034166679355
fmt.Println(d.Minutes())     // 62.0500007613
fmt.Println(d.Seconds())     // 3723.000045678
fmt.Println(d.Nanoseconds()) // 3723000045678

SinceUntil方法可以返回某一时刻与当前时刻的时间间隔。例如:

start := time.Now()
time.Sleep(5 * time.Second)

d := time.Since(start)
fmt.Println(d) // 5.005354572s

d = time.Until(start)
fmt.Println(d) // -5.005509677s

事实上,Since(t)等价于time.Now().Sub(t)Until(t)等价于t.Sub(time.Now())

通过ParseDuration方法可以将一个字符串转化为Duration

d, err := time.ParseDuration("1h2m3s4ms")
if err != nil {
    fmt.Println(err)
} else {
    fmt.Println(d) // 1h2m3.004s
}

Location

Location用来表示不同的时区位置。通过LoadLocation可以加载内置的时区信息,FixedZone可以自定义时区信息。例如:

utc, err := time.LoadLocation("UTC")
local, err := time.LoadLocation("Local")
la, err := time.LoadLocation("America/Los_Angeles")
china := time.FixedZone("china", 8*3600) // +0800, offset in second is 8*3600

LoadLocation方法中,参数可以是UTCLocal以及时区数据库中的名字,如果在时区数据库中查找,会按照如下顺序:

  • ZONEINFO环境变量所指定的zip文件
  • Unix系统中已经安装的
  • $GOROOT/lib/time/zoneinfo.zip

Time

Time表示了纳秒级精度的时间。通过time.Now()可以得到当前时间。

d := time.Now()

fmt.Println(d) // 2017-05-13 16:10:20.938354919 +0800 CST

year, month, day := d.Date()
fmt.Println(year, month, day) // 2017 May 13

year, week := d.ISOWeek()
fmt.Println(year, week) // 2017 19

hour, minute, second := d.Clock()
fmt.Println(hour, minute, second) // 16 10 20

fmt.Println(d.Year())       // 2017
fmt.Println(d.Month())      // May
fmt.Println(d.Day())        // 13
fmt.Println(d.Hour())       // 16
fmt.Println(d.Minute())     // 10
fmt.Println(d.Second())     // 20
fmt.Println(d.Nanosecond()) // 938354919

fmt.Println(d.Weekday()) // Saturday
fmt.Println(d.YearDay()) // 133

fmt.Println(d.Unix())     // 1494663020
fmt.Println(d.UnixNano()) // 1494663020938354919

还可以通过Date方法指定年月日等字段以及时区信息,例如:

la, _ := time.LoadLocation("America/Los_Angeles")
d := time.Date(2006, 1, 2, 15, 4, 5, 0, la)

fmt.Println(d)            // 2006-01-02 15:04:05 -0800 PST
fmt.Println(d.UTC())      // 2006-01-02 23:04:05 +0000 UTC
fmt.Println(d.Local())    // 2006-01-03 07:04:05 +0800 CST
fmt.Println(d.Location()) // America/Los_Angeles

时间运算

  • BeforeAfterEqual方法用来比较时间先后
  • Add方法可以用来加一个Duration得到一个新的时间
  • Sub为两个时间相减得到一个Duration
  • AddDate可以加相应数量的年月日得到一个新的时间
d1 := time.Now()
d2 := d1.Add(10 * time.Second)
d3 := d1.Add(-10 * time.Second)
d4 := d2.Add(-20 * time.Second)
d5 := d1.AddDate(1, 2, 3)

fmt.Println(d1.Before(d2)) // true
fmt.Println(d1.After(d3))  // true
fmt.Println(d3.Equal(d4))  // true
fmt.Println(d2.Sub(d1))    // 10s

fmt.Println(d1) // 2017-05-13 22:14:49.170798749 +0800 CST
fmt.Println(d5) // 2018-07-16 22:14:49.170798749 +0800 CST

格式化

在Go语言中,日期的格式化与其它语言的YYYYMMDD形式差别很大,用的是具体描述形式的形式,参考日期为Mon Jan 2 15:04:05 MST 2006。一些日期格式常量如下:

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"
)

通过Format方法可以格式化日期为字符串形式,例如:

d := time.Now()

fmt.Println(d.Format(time.ANSIC))       // Sun May 14 10:31:27 2017
fmt.Println(d.Format(time.UnixDate))    // Sun May 14 10:31:27 CST 2017
fmt.Println(d.Format(time.RubyDate))    // Sun May 14 10:31:27 +0800 2017
fmt.Println(d.Format(time.RFC822))      // 14 May 17 10:31 CST
fmt.Println(d.Format(time.RFC822Z))     // 14 May 17 10:31 +0800
fmt.Println(d.Format(time.RFC850))      // Sunday, 14-May-17 10:31:27 CST
fmt.Println(d.Format(time.RFC1123))     // Sun, 14 May 2017 10:31:27 CST
fmt.Println(d.Format(time.RFC1123Z))    // Sun, 14 May 2017 10:31:27 +0800
fmt.Println(d.Format(time.RFC3339))     // 2017-05-14T10:31:27+08:00
fmt.Println(d.Format(time.RFC3339Nano)) // 2017-05-14T10:31:27.67117435+08:00
fmt.Println(d.Format(time.Kitchen))     // 10:31AM
fmt.Println(d.Format(time.Stamp))       // May 14 10:31:27
fmt.Println(d.Format(time.StampMilli))  // May 14 10:31:27.671
fmt.Println(d.Format(time.StampMicro))  // May 14 10:31:27.671174
fmt.Println(d.Format(time.StampNano))   // May 14 10:31:27.671174350

fmt.Println(d.Format("2006-01-02 15:04:05")) // 2017-05-14 10:31:27

Format方法相反,Parse方法可以将字符串转换为时间。例如:

s := time.Now().Format(time.ANSIC)
fmt.Println(s) // Sun May 14 10:38:27 2017

d, _ := time.Parse(time.ANSIC, s)
fmt.Println(d) // 2017-05-14 10:38:27 +0000 UTC

d, _ = time.Parse("2006-01-02 15:04:05", "2000-01-01 00:00:00")
fmt.Println(d) // 2000-01-01 00:00:00 +0000 UTC

d, _ = time.ParseInLocation("2006-01-02 15:04:05", "2000-01-01 00:00:00", time.Local)
fmt.Println(d) // 2000-01-01 00:00:00 +0800 CST

Timer

Timer是一个定时器,结构如下:

type Timer struct {
    C <-chan Time
    // contains filtered or unexported fields
}

Timer必须由NewTimer或者AfterFunc方法创建。Timer本身有ResetStop方法,用来重置活着取消定时器。例如:

t1 := time.NewTimer(2 * time.Second)
<-t1.C
fmt.Println("timer1 expired")

t2 := time.NewTimer(2 * time.Second)
t2.Stop()
fmt.Println("timer2 stoped")

f := func() {
    fmt.Println("function executed")
}
time.AfterFunc(2*time.Second, f)
// 确保主goroutine比子goroutine晚退出
// 不然不会打印"function executed"
time.Sleep(3 * time.Second)

t3 := time.NewTimer(1 * time.Millisecond)
t3.Reset(2 * time.Second)
<-t3.C
fmt.Println("timer3 expired")

其它方法

Sleep

暂停一段时间,例如:

fmt.Println("hello")
time.Sleep(time.Second)
fmt.Println("world")

After

该函数参数为一个Duration,返回一个<- chan Time。等待结束后,chnnel的输出值为当前时间。例如:

fmt.Println(time.Now()) // 2017-05-15 23:20:29.196462261 +0800 CST
c := time.After(2 * time.Second)
fmt.Println(<-c) // 2017-05-15 23:20:31.201923491 +0800 CST

Tick

该方法与After方法类似,也是参数为一个Duration,返回一个<- chan Time。不过是每过间隔时间channel中就会输出数据,即当前时间。例如:

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

// 2017-05-15 23:23:21.318468768 +0800 CST
// 2017-05-15 23:23:22.318531626 +0800 CST
// 2017-05-15 23:23:23.318468491 +0800 CST
// 2017-05-15 23:23:24.318512446 +0800 CST
// 2017-05-15 23:23:25.313375396 +0800 CST
// ...