『Go 內置庫第一季:time』

你們好,我叫謝偉,是一名程序員。程序員

近期會更新內置庫的學習筆記,主要參考文獻來自於官方文檔和源代碼。數據庫

本節的主題:timejson

時間的操做在項目中使用的很是頻繁,好比說數據庫中,常常有時間的操做,好比根據時間進行劃分,統計之類的功能。後端

那麼如何學會經常使用的操做呢?數組

大綱:bash

  • 本身總結的經常使用操做
  • 官方的 API
  • 學習總結

本身總結的經常使用操做

時間類型的數據,咱們在項目中都會進行哪些操做呢?服務器

要在思惟裏掌握時間類型的數據的操做,又應該如何梳理呢?函數

1. 時間的單位

暫時撇開代碼層面,平常生活中關於時間的單位都有哪些呢?佈局

  • 毫秒

通常到毫秒層面就夠了,固然還能夠繼續劃分:微秒、納秒...學習

那時間的單位的轉換是如何進行的呢?

  • 1 y = 12 m
  • 1 m = 4 w
  • 1 w = 7 d
  • 1 d = 24 h
  • 1 h = 60 min
  • 1 min = 60 s
  • 1 s = 1000 ms
  • 1 ms = 1000 us
  • 1 us = 1000 ns

爲何要了解這些啊? 這不是常識嗎?是的。常常有常識性的問題,轉換成代碼層面而出錯。因此有必要進行了回顧。

2. 時間操做

瞭解了時間的基本單位,那就好辦了。

func main(){
	now := time.Now()

	fmt.Println(now.Year())
	fmt.Println(now.Month())
	fmt.Println(now.Day())
	fmt.Println(now.Hour())
	fmt.Println(now.Minute())
	fmt.Println(now.Second())
	fmt.Println(now.Date())

}
>>
2018-11-13 22:30:03.500763 +0800 CST m=+0.000810351
2018
November
13
22
30
3
2018 November 13
複製代碼

全部這些時間的單位底層都是 int 類型。既然是 int 類型,那 November 是如何獲得的?

很簡單,底層定義這樣一個關於月份的數組,將對應的位置的值返回便可。

var months = [...]string{
	"January",
	"February",
	"March",
	"April",
	"May",
	"June",
	"July",
	"August",
	"September",
	"October",
	"November",
	"December",
}
複製代碼

3. 時間戳

  • 時間戳的使用也很是普遍,好比爲了表示惟一性
  • 時間戳的概念:1970年01月01日00時00分00秒(北京時間1970年01月01日08時00分00秒)起至如今的總秒數

時間戳,這個概念,若是不是程序員,可能完成沒有必要了解,有更好的閱讀時間的顯示方式,不必知道這麼一串數字。

在 Go 中,如何將時間轉換成時間戳?

func main(){
    now := time.Now()
    
	fmt.Println(now.UnixNano())
	fmt.Println(now.Unix())
}
>>
1542119403501037000
1542119403
複製代碼

上文一個轉換爲納秒,一個是轉換爲秒。能夠看到轉換單位是 10^9

那如何將時間戳轉換爲 時間類型?

func main(){

    fmt.Println(time.Unix(1542119403, 1542119403000000000))
    
    fmt.Println(time.Unix(1542119403, 1542119403000000000).UTC())

}

>>
2067-09-26 13:00:06 +0800 CST
2067-09-26 05:00:06 +0000 UTC
複製代碼

關於時間,還存在一個重要的概念,即:時區

  • UTC 校準的全球時間
  • CST China Standard Time UT 8:00

因此常常會出現時間相差 8 小時的狀況,好比,本地程序運行正常,推送到倉庫中,自動構建夠,程序得不到預期的值,有多是由於服務器的時間的時區和本地的不一致。

4. 時間和字符串的相互轉化

涉及時間的顯示的佈局有個默認值:2006-01-02 15:04:05

這個時間的速記:12345

func main(){
    
    now := time.Now()
	fmt.Println(now.Format("2006-01-02 15:04:05"))
}

	timeString := "2019-01-02 15:03:00"

	fmt.Println(time.Parse("2006-01-02 15:04:05", timeString))
	fmt.Println(time.ParseInLocation("2006-01-02 15:04:05", timeString, time.Local))

>>
2018-11-13 22:59:08
2019-01-02 15:03:00 +0000 UTC <nil>
2019-01-02 15:03:00 +0800 CST <nil>
複製代碼

還記得以前字符串和基本數據類型(整型、浮點型、布爾型)相互轉化的章節。

咱們總結:

  • 基本數據類型轉化爲字符串:帶關鍵字 Format, 且沒有錯誤返回
  • 字符串轉化爲基本數據類型:帶關鍵字 Parse , 且存在錯誤返回

時間類型和字符串之間的轉化和上文的總結一致。

啓發:使用關鍵字:Format 、 Parse 對本身函數進行命名組織;沒有錯誤類型的函數不返回錯誤類型

有時候咱們可能只須要時間的部分值,好比說,只須要整點的值,那關於這些操做,又應該如何操做呢?

func main(){
    timeToString()
}

var timeToString = func() {

	now := time.Now()

	fmt.Println(now.Format("2006-01-02 15:00:00"))
	fmt.Println(now.Format("2006-01-02 15:04:00"))
	fmt.Println(now.Format("2006-01-02 00:00:00"))

	fmt.Println(now.Round(time.Hour))
	fmt.Println(now.Round(time.Minute))
	fmt.Println(now.Round(time.Second))
	fmt.Println(now.Truncate(time.Hour))
	fmt.Println(now.Truncate(time.Minute))
	fmt.Println(now.Truncate(time.Second))

}
>>
2018-11-13 23:00:00
2018-11-13 23:12:00
2018-11-13 00:00:00
2018-11-13 23:00:00 +0800 CST
2018-11-13 23:13:00 +0800 CST
2018-11-13 23:12:34 +0800 CST
2018-11-13 23:00:00 +0800 CST
2018-11-13 23:12:00 +0800 CST
2018-11-13 23:12:33 +0800 CST
複製代碼

能夠看出,存在兩種方法,一種是操做 佈局,即更改那個默認值 2006-01-02 15:04:05; 一種是使用內置的 Round, Truncate 兩種的區別是Round 向上取整,Truncate 向下取整

5. 兩個時間之間的操做

上面的例子絕大多數是單個時間的操做,好比取時間戳、時間和字符串之間轉化、獲取時間的年月日等。

平常操做中,兩個時間的操做也是比較頻繁的。

好比:

  • 判斷一個時間是不是在該時間以前、以後
  • 給出給定時間的某個時間節點的值:好比 1小時前、1天前、1年前、1年後、1天后、1小時後等
func main(){
    timeOp()

}

var timeOp = func() {
	now := time.Now()

	fmt.Println(now.Add(1 * time.Hour))
	fmt.Println(now.Add(24 * time.Hour))
	fmt.Println(now.Add(-10 * time.Hour))
}

>>
2018-11-14 00:21:47.48055 +0800 CST m=+3600.000854277
2018-11-14 23:21:47.48055 +0800 CST m=+86400.000854277
2018-11-13 13:21:47.48055 +0800 CST m=-35999.999145723
複製代碼

獲得 1小時後、1天后、10小時前

好,那這些時間先後都有哪些值能夠選擇?

const (
	Nanosecond  Duration = 1
	Microsecond          = 1000 * Nanosecond
	Millisecond          = 1000 * Microsecond
	Second               = 1000 * Millisecond
	Minute               = 60 * Second
	Hour                 = 60 * Minute
)
複製代碼

這些常量,輔以恰當的運算。

那 1年前咋搞?還運算嗎?傻瓜。

func main(){
    timeOpDate()
}

var timeOpDate = func() {
	now := time.Now()

	fmt.Println(now.AddDate(-1, 0, 0))
	fmt.Println(now.AddDate(2, 0, 0))
	fmt.Println(now.AddDate(0, 1, 0))
}
>>
2017-11-13 23:26:18.697797 +0800 CST
2020-11-13 23:26:18.697797 +0800 CST
2018-12-13 23:26:18.697797 +0800 CST
複製代碼

完成啦。

基本上這兩個函數就能夠完成目的。

那如何計算兩個時間之間的差呢?

func main(){
    timeInterval()
}

var timeInterval = func() {
	now := time.Now()
	stringTime := "2018-11-14 20:00:00"

	newTime, _ := time.ParseInLocation("2006-01-02 15:04:05", stringTime, time.Local)

	if newTime.After(now) {
		subTime := newTime.Sub(now)
		fmt.Println("newTime after now")
		fmt.Println(subTime.Hours())
		fmt.Println(subTime.Minutes())
		fmt.Println(subTime.Seconds())
		fmt.Println(subTime.Nanoseconds())
	}
	if newTime.Before(now) {
		subTime := now.Sub(newTime)
		fmt.Println(subTime.String())
	}
}
>>
newTime after now
20.463746377777777
1227.8247826666666
73669.48696
73669486960000
複製代碼

6. 其餘

  • 得出時間是本週的周幾
  • 得出時間是該年的第幾周
func main(){
	fmt.Println(time.Now().ISOWeek())
	fmt.Println(time.Now().Weekday())
}
>>
2018 46
Tuesday
複製代碼

官方API

大概咱們沒講有這些內容:

  • 定時器?
  • 底層是如何獲取時間的?
  • 序列化和反序列化(還記得 json 那節 Marshler 嗎)
func (t Time) MarshalJSON() ([]byte, error)

MarshalJSON implements the json.Marshaler interface. The time is a quoted string in RFC 3339 format, with sub-second precision added if present.
複製代碼

自定義了序列化的結構

總結

枚舉類型在 Go 裏面的時候,用來表示連續的遞增的值。

好比想表示顏色、好比想表示星期幾

這種連續的值,通常都選擇枚舉類型來定義。

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

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

好比想自定義的顏色順序:

const (
	Red = iota
	Orange
	Yellow
	Green
	Cyan
	Blue
	Purple
)

func main(){
    	fmt.Println(Red,
		Orange,
		Yellow,
		Green,
		Cyan,
		Blue,
		Purple)
}

>>
0 1 2 3 4 5 6
複製代碼

固然提到枚舉,考點不會這樣考你,而是以下面的操做:

const (
	Red = iota
	Orange
	Yellow = iota + 10
	Green = iota
	Cyan
	Blue = 10
	Purple
)


複製代碼

問你各個值得多少?

0 1 12 3 4 10 10

複製代碼

<完>

相關文章
相關標籤/搜索