本篇開始介紹Go中的time套件,時間處裡是Go程式的核心之一,time套件官方文件
Go 中,時間資料會是 time.Time 結構型別。
package main
import "fmt"
func main() {
start := time.Now() //取得當下系統時間
fmt.Println("程式開始時間:" , start)
fmt.Println("資料處理中...")
time.Sleep(2 * time.Second) // 讓程式停兩秒
end := time.Now() //再次取得當下系統時間
fmt.Println("程式結束時間:", end)
}
結果 :
以上時間值實際上分為兩個部分 :
wall clock 就是所謂的電腦系統時間,會透過NTP(network time protocal, 網路時間協定)來同步。而 monotonic clock 是程序啟動後經過的時間(單位為奈秒),它不會跟外界同步,可能在關機後就停擺,唯一的功能 : 拿來比較時間。
Go 語言時間值一定包括 wall clock 值,但不一定有 monotonic clock 值,而在使用time套件時也不必擔心這個細節。
package main
import (
"fmt"
"time"
)
func main() {
now := time.Now() //當下時間
day := now.Weekday() //取星期幾
hour := now.Hour() //取得小時
fmt.Println("Day:", day, "/ hour:", hour)
if day.String() == "Monday" && (hour >= 0 && hour <2) {
fmt.Println("執行全功能測試")
}else{
fmt.Println("執行簡易測試")
}
}
time.Time結構常用 :
方法名稱 | 描述 | 回傳值 |
---|---|---|
Date() |
獲取年、月、日 | int, time.Month, int |
Day() |
獲取日期(1-31) | int |
Month() |
獲取月份 | time.Month |
Year() |
獲取年份 | int |
Hour() |
獲取小時(0-23) | int |
Minute() |
獲取分鐘(0-59) | int |
Second() |
獲取秒數(0-59) | int |
Nanosecond() |
獲取奈秒 | int |
Weekday() |
獲取星期幾 | time.Weekday |
YearDay() |
獲取年中的第幾天(1-366) | int |
IsZero() |
判斷 Time 值是否為零時間 |
bool |
After(u) |
判斷時間是否在另一時間之後 | bool |
Before(u) |
判斷時間是否在另一時間之前 | bool |
Equal(u) |
判斷兩個時間是否相等 | bool |
Add(d) |
加上一段時間 | time.Time |
Sub(u) |
計算兩個時間的差值 | time.Duration |
Format(layout) |
根據指定的格式格式化時間 | string |
Local() |
轉換時間為本地時區 | time.Time |
UTC() |
轉換時間為UTC時區 | time.Time |
Unix() |
獲取從1970年1月1日至今的秒數 | int64 |
MarshalJSON() |
將時間轉換為JSON格式 | []byte, error |
對於月分和星期幾,time套件也有定一相關常數。
而且在Go語言中如果要將int轉為string,就得是用strconv套件提供的轉換功能:
package main
import (
"fmt"
"strconv"
"time"
)
func main() {
appName := "HTTPCHECKER"
action := "BASIC"
date := time.Now()
logFileName := appName + "_" + action + "_" +
strconv.Itoa(date.Day()) + ".log"
fmt.Println("log檔案名稱:", logFileName)
}
time.Time 結構的 Format() 方法可以將時間轉成特定格式字串:
func (t Time) Format(layout string) string
**參數layout為時間格式字串。**關於這個time套件也定義一系列常數 :
常數名稱 | 描述 | 值 |
---|---|---|
ANSIC |
預設的 ANSIC 格式 | "Mon Jan _2 15:04:05 2006" |
UnixDate |
預設的 Unix 格式 | "Mon Jan _2 15:04:05 MST 2006" |
RubyDate |
預設的 Ruby 格式 | "Mon Jan 02 15:04:05 -0700 2006" |
RFC822 |
RFC 822 格式 | "02 Jan 06 15:04 MST" |
RFC822Z |
RFC 822 with numeric zone 格式 | "02 Jan 06 15:04 -0700" |
RFC850 |
RFC 850 格式 | "Monday, 02-Jan-06 15:04:05 PST" |
RFC1123 |
RFC 1123 格式 | "Mon, 02 Jan 2006 15:04:05 PST" |
RFC1123Z |
RFC 1123 with numeric zone 格式 | "Mon, 02 Jan 2006 15:04:05 -0700" |
RFC3339 |
RFC 3339 格式 | "2006-01-02T15:04:05Z07:00" |
RFC3339Nano |
RFC 3339 with nanoseconds 格式 | "2006-01-02T15:04:05.999999999Z07:00" |
Kitchen |
Kitchen format 格式 | "3:04PM" |
Stamp |
Stamp format 格式 | "Jan _2 15:04:05" |
StampMilli |
Stamp with millisecond format 格式 | "Jan _2 15:04:05.000" |
StampMicro |
Stamp with microsecond format 格式 | "Jan _2 15:04:05.000000" |
StampNano |
Stamp with nanosecond format 格式 | "Jan _2 15:04:05.000000000" |
範例 :
package main
import(
"fmt"
"time"
)
func main() {
fmt.Println(time.Now().Format(time.ANSIC))
fmt.Println(time.Now().Format(time.UnixDate))
fmt.Println(time.Now().Format(time.RFC3339))
fmt.Println(time.Now().Format("2006/1/2 3:4:5") //自訂時間格式
}
一些細節規則請看官方文件 : 時間格式官方文件
Go 語言使用一個叫 "magical reference data" 的字串,讓你自訂時間格式。
在 Go 語言的 time 套件中,有一些預定義的格式常數,這些常數通常被用來格式化和解析日期和時間。以下是其中的一些常用的時間格式常數及其對應的值,每個值會照順序對應1234567:
月 | 日 | 時 | 分 | 秒 | 年 | 時區 |
---|---|---|---|---|---|---|
Jan | 2 | 15 | 04 | 05 | 2006 | -0700 |
1 | 2 | 3 | 4 | 5 | 6 | 7 |
"2006-01-02 15:04:05" 在 Go 語言的 time 套件中是一個特殊的時間格式。這並不是隨便選擇的日期,而是有特定的含義。在 Go 中,這個日期時間對應到:
這個時間格式是基於 Go 語言之父 Rob Pike 的建議選擇的,主要是因為它獨特(每個部分的數字都不同),所以在格式化和解析時間時不會造成混淆。
當你使用 time.Format 或 time.Parse 來格式化或解析時間時,你可以使用這個特定日期時間的任何部分來指示你想要的輸出格式。例如:
這樣的設計方式有助於使時間格式化和解析在 Go 中變得直觀。而不是使用一些其他語言中的碼(例如 %Y、%m、%d 等),你只需要使用這個特定的日期時間組合。
以下是 time.Date() 函數的一些使用範例:
t := time.Date(2023, time.January, 15, 0, 0, 0, 0, time.UTC)
fmt.Println(t) // 輸出: 2023-01-15 00:00:00 +0000 UTC
t := time.Date(2023, time.January, 15, 14, 30, 0, 0, time.UTC)
fmt.Println(t) // 輸出: 2023-01-15 14:30:00 +0000 UTC
loc, _ := time.LoadLocation("Asia/Taipei")
t := time.Date(2023, time.January, 15, 14, 30, 0, 0, loc)
fmt.Println(t) // 這將會輸出該時區的對應時間
AddDate() 方法允許你向 time.Time 值添加(或減少)指定的年、月和日。這是一個方便的方法,用於計算從特定日期開始的相對日期。
以下是使用 time.AddDate() 方法的一些示例:
t := time.Now()
newTime := t.AddDate(1, 2, 3)
fmt.Println("Original Time:", t)
fmt.Println("New Time:", newTime)
t := time.Now()
newTime := t.AddDate(-1, -2, 0)
fmt.Println("Original Time:", t)
fmt.Println("New Time:", newTime)
t := time.Now()
newTime := t.AddDate(0, 0, 10)
fmt.Println("Original Time:", t)
fmt.Println("New Time:", newTime)
func (t Time) In(loc *Location) Time
這個方法是 time.Time 結構的一個方法。此方法用於將 Time 值從它當前的時區轉換到指定的時區 loc,並回傳新的 Time 值。
time 套件中的時區time.Location結構型別,之前使用time.UTC、time.Local 都屬與這種結構型別。
如果想使用特定時區、甚至是建立自定時區,有兩種方式 :
loc, err := time.LoadLocation("Asia/Taipei")
if err != nil {
fmt.Println("Error:", err)
return
}
t := time.Now().In(loc)
fmt.Println("Time in Asia/Taipei:", t)
這裡的 "Asia/Taipei" 是 IANA 時區資料庫中的一個時區名稱。
offset := 8 * 60 * 60 // 偏移量為8小時,轉換為秒
loc := time.FixedZone("MyTimeZone", offset)
t := time.Now().In(loc)
fmt.Println("Time in MyTimeZone:", t)
這裡的 "MyTimeZone" 是你給定的自定義時區名稱,而偏移量是從 UTC 時間計算的秒數。
範例 :
package main
import (
"fmt"
"time"
)
func main() {
// 獲得當前的時間(可能是本地時區或UTC,取決於系統設定)
now := time.Now()
// 輸出當前時間
fmt.Println("Current Time:", now)
// 使用time.LoadLocation()取得特定時區(例如 "Asia/Taipei")
taipei, err := time.LoadLocation("Asia/Taipei")
if err != nil {
fmt.Println("Error:", err)
return
}
// 使用In()方法將時間轉換到指定的時區
taipeiTime := now.In(taipei)
// 輸出轉換後的時間
fmt.Println("Time in Asia/Taipei:", taipeiTime)
}
ParseInLocation() 是 time 包中的一個功能,它允許你根據指定的layout和字串解析日期和時間,并同時指定時區。當你知道字串代表的時區,且希望確保轉換過程中使用該時區時,可以使用這個。
ParseInLocation() 函式:
func ParseInLocation(layout, value string, loc *Location) (Time, error)
範例 :
package main
import (
"fmt"
"time"
)
func main() {
const layout = "2006-01-02 15:04:05"
value := "2023-10-01 14:15:45"
// 要哪個時區
location, err := time.LoadLocation("Asia/Taipei")
if err != nil {
fmt.Println("Error:", err)
return
}
// 轉換時間值到特定時區
t, err := time.ParseInLocation(layout, value, location)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Parsed time:", t)
}
在上述範例中,我們首先定義了日期和時間的格式(layout)。然後,我們將字串 value 在 "Asia/Taipei" 時區的上下文中轉換成 time.Time 值。
ParseInLocation() 與 Parse() 的主要區別在於,Parse() 假定字串表示的是UTC時間,除非字符串本身指定了時區。而 ParseInLocation() 允許你明確地指定字串應該在哪個時區上下文中解析,即使字串本身不包含時區信息。
time.Time
提供了幾個方法來比較兩個時間值。以下是 Equal(), Before(), 和 After() 方法的詳細說明和比較:
方法定義:func (t Time) Equal(u Time) bool
說明:Equal 比較時間 t 和 u 是否代表同一時刻。因為time.Time 值可能是在不同的時區,這個方法會考慮時區的轉換,所以即使兩個時間值在不同的時區,只要他們代表的是同一時刻,就會返回 true。
方法定義:func (t Time) Before(u Time) bool
說明:Before 比較時間 t 是否在 u 之前。它不會考慮時區,所以兩個 time.Time 值即使在不同的時區,只要 t 在 u 之前,就會返回 true。
方法定義:func (t Time) After(u Time) bool
說明:After 比較時間 t 是否在 u 之後。這個方法的行為與 Before 相似,但方向相反。它同樣不考慮時區。
範例:
package main
import (
"fmt"
"time"
)
func main() {
t1 := time.Date(2023, 10, 1, 12, 0, 0, 0, time.UTC)
t2 := time.Date(2023, 10, 1, 14, 0, 0, 0, time.UTC)
fmt.Println("t1 equals t2:", t1.Equal(t2))
fmt.Println("t1 is before t2:", t1.Before(t2))
fmt.Println("t1 is after t2:", t1.After(t2))
}
執行結果 :
t1 equals t2: false
t1 is before t2: true
t1 is after t2: false
有時候我們會需要計算程式的耗費時間、或對網站做壓力測試,如果要測量某段執行時間,只需要在該程式頭尾各取一次當下系統時間,然後用第二個時間Sub()減去第一個時間值:
func (t Time) Sub(u Time) Duration
以下是一個簡單的Go示例,演示如何測量某段程式碼的執行時間:
package main
import (
"fmt"
"time"
)
func main() {
// 開始時間
startTime := time.Now()
// 在這裡放置你要測試的程式碼
// 例如,你可以執行一個循環或計算一個複雜的運算
// 結束時間
endTime := time.Now()
// 計算執行時間
elapsedTime := endTime.Sub(startTime)
fmt.Printf("程式執行時間:%v\n", elapsedTime)
}
範例 :
package main
import (
"fmt"
"time"
)
func main() {
// 開始時間
startTime := time.Now()
// 在這裡放置你要測試的程式碼
// 例如,你可以執行一個循環或計算一個複雜的運算
// 結束時間
endTime := time.Now()
// 計算執行時間
elapsedTime := endTime.Sub(startTime)
fmt.Printf("程式執行時間:%v\n", elapsedTime)
}
在這個示例中,我們使用time.Now()來獲取開始時間和結束時間,然後使用Sub()方法計算它們之間的差距,最後印出執行時間。
在Go語言中,time包提供了一些有用的函數和方法來處理時間和持續時間。
其中包括time.Since()和time.Until()方法。
time.Since()函數返回自某個時間點以來的持續時間(從某個時間點到現在系統時間)。。
寫法相當於 :
time.Since(<時間值>)
//time.Now().Sub(<時間值>)
下面是一個示例:
package main
import (
"fmt"
"time"
)
func main() {
startTime := time.Now() // 獲取開始時間
// 在這裡放置你要測試的程式碼
time.Sleep(2 * time.Second) // 模擬一些工作
endTime := time.Now() // 獲取結束時間
// 使用time.Since()計算持續時間
elapsedTime := time.Since(startTime)
fmt.Printf("程式執行時間:%v\n", elapsedTime)
}
在這個示例中,我們使用time.Now()來獲取開始和結束時間,然後使用time.Since()函數計算兩者之間的持續時間。這允許我們測量程式碼執行的實際時間。
可計算當下系統時間到未來時間點還有多久 :
time.Until(<時間值>)
//(<時間值>.Sub(time.Now()))
下面是一個示例:
package main
import (
"fmt"
"time"
)
func main() {
// 定義一個未來時間點
futureTime := time.Now().Add(2 * time.Hour)
// 使用time.Until()計算未來時間與當前時間的差距
durationUntil := time.Until(futureTime)
fmt.Printf("距離未來時間還有:%v\n", durationUntil)
}
以上就是有關於時間的部分整理