Go中的time操做

程序開發中,時間操做是不可避免的,在這裏記錄一下Go中常見的操做。bash

Duration

Go中的時間最底層的數據結構爲Duration, 在Duration的基礎上,咱們定義了下面的概念:數據結構

const (
    Nanosecond Duration = 1 // 納秒,計算Duration的是使用ns
    Microsecond = 1000 * Nanosecond 微秒,計算Duration的是使用us
    Millisecond = 1000 * Microsecond 毫秒, 計算Duration的是使用ms
    Second      = 1000 * Millisecond 秒,計算Duration的是使用s
    Minute      = 60 * Second 分,計算Duration的是使用m
    Hour        = 60 * Minute 時,計算Duration的是使用h
)
複製代碼

那麼Duration能夠如何操做呢?函數

  • time.Duration
seconds := 10
time.Duration(seconds)*time.Second // 返回Duration結構
複製代碼
  • time.ParseDuration ParseDutation主要用於解析字符串,使用字符串的能夠避免使用time.Duration不方便表示的時間段。
hours, _ := time.ParseDuration("10h") // 生成10個小時的duration 
complex, _ := time.ParseDuration("1h10m10s") // 生成1小時10分鐘10秒的duration
micro, _ := time.ParseDuration("1µs") // 生成1微妙的duration
複製代碼
  • time.Sub

如何計算兩個時間的時間差,返回Duration結構?注意ui

start := time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)
end := time.Date(2000, 1, 1, 12, 0, 0, 0, time.UTC)

difference := end.Sub(start)
fmt.Printf("difference = %v\n", difference)
複製代碼
  • time.Since

time.Since等價於time.Now().Sub(t),用於計算當前時間和以前某個時間的時間差。spa

  • time.Until

time.Until等價於t.Sub(time.Now()),用於計算以後的某個時間和當前時間的時間差。code

那麼Duration究竟是什麼數據結構呢?Duration只是int64的一種暱稱,在此之上也實現多種方法,如.Hours(),.Minutes(),.Seconds()等。orm

type Duration int64
複製代碼

Location

通常狀況不須要設置Location,若是要設置location,可以在哪些地方使用呢? 首先是在time.Date構造time.Time的過程當中,最後一個參數設置當前時間所在時區。對象

Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location)
複製代碼

那麼time.Location如何初始化呢?使用time.LoadLocation來加載開發

location, err := time.LoadLocation("America/Los_Angeles")
timeInUTC := time.Date(2018, 8, 30, 12, 0, 0, 0, time.UTC) // time.UTC是*Location結構
複製代碼

帶時區的時間轉化,字符串

t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) // 當前時間爲UTC時間
fmt.Printf("Go launched at %s\n", t.Local()) // t.Local轉化本地時間, 2009-11-11 07:00:00 +0800 CST。
複製代碼

東八區怎麼表示呢?

// 方法一 
l,_ := time.LoadLocation("Asia/Shanghai") 

// 方法二,可能用的很少,定義一個名字,而後自行計算時區+-12 * 3600 
var cstZone = time.FixedZone("CST", 8*3600)       // 東八
fmt.Println(time.Now().In(cstZone).Format("01-02-2006 15:04:05"))
複製代碼

爲何是乘3600呢?從秒開始計算,下面兩行獲得北京時區。

secondsEastOfUTC := int((8 * time.Hour).Seconds())
beijing := time.FixedZone("Beijing Time", secondsEastOfUTC) 
複製代碼

Ticker

type Ticker struct {
    C <-chan Time // channel 每隔固定的時間會發送消息
}
複製代碼

每隔固定的時間會發送信號,這個固定時間怎麼獲取呢?經過NewTicker接收Duration對象獲取,下面代碼演示了每一個1秒打印,打印10秒的功能。

ticker := time.NewTicker(time.Second)
defer ticker.Stop() // 【重要】關閉ticker
done := make(chan bool)
go func() {
    time.Sleep(10 * time.Second)
    done <- true
}()
for {
    select {
    case <-done:
        fmt.Println("Done!")
        return
    case t := <-ticker.C:
        fmt.Println("Current time: ", t)
    }
}
複製代碼

Time

Time是操縱時間的核心對象。

  • time.Parse,time.ParseInLocation
time.Parse(layout, string) // 獲取指定字符串表明的時間
time.ParseInLocation(layout, value string, loc *Location) // 帶上時區的時間
複製代碼

今天開發中遇到一個問題,計算兩個時間相差多少秒?

todayEnd, _ := time.Parse(timeLayout, fmt.Sprintf("%s %s", time.Now().Format("2006-01-02"), "23:59:59"))
todayStart := time.Now()
validSeds := todayEnd.Sub(todayStart).Minutes()
fmt.Println("validSeds: ", int(validSeds)) 
複製代碼

上面的代碼計算時間一直不正確,就是由於time.Parse獲取出來的時間是相對0時區的,而time.Now使用的是本地時區,須要將其中Parse出的代碼修爲下面形式:

l, _ := time.LoadLocation("Asia/Shanghai")
todayEnd, _ := time.ParseInLocation(timeLayout, fmt.Sprintf("%s %s", time.Now().Format("2006-01-02"), "23:59:59"), l)
複製代碼
  • time.Unix, time.UnixNano

計算當前的時間戳

time.Unix() // 秒級 time.UnixNano() // 毫秒級

  • time.Add

增長一個Duration

  • time.AddDate
play 

start := time.Date(2009, 1, 1, 0, 0, 0, 0, time.UTC)
oneDayLater := start.AddDate(0, 0, 1) // 增長一天
oneMonthLater := start.AddDate(0, 1, 0) // 增長一月
oneYearLater := start.AddDate(1, 0, 0) // 增長一年 
複製代碼

不過AddDate均可以使用Add+Duraion組合解決。

  • t.After,t.Before

比較兩個時間的前後

year2000 := time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)
year3000 := time.Date(3000, 1, 1, 0, 0, 0, 0, time.UTC)

isYear3000AfterYear2000 := year3000.After(year2000) // True
isYear2000AfterYear3000 := year2000.After(year3000) // False

isYear3000BeforeYear2000 := year3000.Before(year2000) // false
isYear2000BeforeYear3000 := year2000.Before(year3000) // true
複製代碼
  • t.Date, t.Clock
func (t Time) Clock() (hour, min, sec int) // 返回t的時分秒 
func (t Time) Date() (year int, month Month, day int) // 返回t的年月日
複製代碼
  • t.Format 時間格式化顯示

  • t.In 經過複製的方式,改變當前時間的時區

func (t Time) In(loc *Location) Time
複製代碼
  • t.IsZero

聲明time.Time未賦值,改值爲January 1, year 1, 00:00:00 UTC.

  • t.Local, t.UTC

分別使用本地時區生成時間, 0時區生成時間。

  • t.Zone()

返回當前時區的名稱和偏移0時區多少秒

t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.Local)
name, offset := t.Zone()
fmt.Println(name, offset) // CST 28800(8*3600)
複製代碼

Timer

Timer是個什麼東西?最基本仍是個channel

type Timer struct {
    C <-chan Time // 時間到了,發送信號,作好接收準備
}
複製代碼

怎麼初始化Timer呢?

func NewTimer(d Duration) *Timer
複製代碼

時間到了,要執行什麼函數呢?

func AfterFunc(d Duration, f func()) *Timer 複製代碼

中途若是想着stop定時器,怎麼辦?

func (t *Timer) Stop() bool 複製代碼

爲了確保關閉?

if !t.Stop() {
	<-t.C
}
複製代碼

Month、Weekday

兩個封裝的方式相同,使用暱稱的方式掛載更多的方法,是變量可以存在更多的可能性。

// Month
type Month int
const (
    January Month = 1 + iota
    February
    March
    April
    May
    June
    July
    August
    September
    October
    November
    December
)
func (m Month) String() string{}

// Weekday 
type Weekday int 
const (
    Sunday Weekday = iota
    Monday
    Tuesday
    Wednesday
    Thursday
    Friday
    Saturday
)
func (d Weekday) String() string 複製代碼
相關文章
相關標籤/搜索