タイムパッケージの紹介
通常、時間には時間値とタイムゾーンが含まれます。これは、Go 言語の time パッケージのソース コードから確認できます。
type Time struct{
// wallとextは、壁時刻秒、壁時刻ナノ秒、および必要に応じてナノ秒の単調な時計読み取りをエンコードします。
//
// 上位ビットから下位ビットの位置にわたって、ウォールは1ビットのフラグ(hasMonotonic)、
// 33ビットの秒フィールド、30ビットのウォール時間ナノ秒フィールドをエンコードします。
// ナノ秒フィールドは、[0、999999999]の範囲にあります。
// hasMonotonicビットが0の場合、33ビットのフィールドはゼロであり、
// Jan 1 year 1以来の完全な符号付き64ビットのウォール秒がextに保管されます。
// hasMonotonicビットが1の場合、33ビットのフィールドには、Jan 1 year 1885以来の33ビットの
// unsigned wall秒が含まれ、extには、プロセス開始以来の符号付き64ビットの単調なクロック読み取り、ナノ秒が含まれます。
wall uint64
ext int64
// locは、このTimeに対応する分、時、月、日、年を決定するために使用すべきLocationを指定します。
// nilロケーションはUTCを意味します。
// すべてのUTC時間はloc==nilで表され、loc==&utcLocではありません。
loc *Location
}
上記のコードでは次のようになります。
- Wall: 西暦 1 年 1 月 1 日の 00:00:00 UTC からの秒数を示します。
- ext: ナノ秒を示します。
- loc: タイムゾーンを表し、主にオフセットを扱います。異なるタイムゾーンは異なる時刻に対応します。
時間を正しく表現するにはどうすればよいでしょうか?
最も正確な計算は、標準時(国際原子時)としても定義されている「原子振動周期」を用いて計算される物理時計(Atomic Clock、原子時計とも呼ばれます)であると認識されています。
私たちがよく目にするUTC(協定世界時)は、この原子時計をベンチマークとして定義された正しい時刻です。 UTC標準時はGMT(グリニッジ標準時、グリニッジ標準時)に基づいているため、現地時間とUTC時間の時差は、現地時間とGMT時間の時差になります。
Go 言語の time パッケージには、次の 2 つのタイム ゾーン変数があります。
- time.UTC: UTC 時間
- time.Local: 現地時間
同時に、Go 言語では、次のように、タイム ゾーン変数を取得するための LoadLocation メソッドとFixedZone メソッドも提供します。
FixedZone(name string, offset int) *Location
このうち、name はタイムゾーンの名前、offset は UTC までの時差です。
LoadLocation(name string) (*Location, error)
このうち、nameはタイムゾーンの名前です。
時間取得
1) 現在時刻を取得する
time.Now() 関数を通じて現在の時刻オブジェクトを取得し、イベント オブジェクトを通じて現在の時刻情報を取得できます。サンプルコードは次のとおりです。
package main
import (
"fmt"
"time"
)
func main() {
now := time.Now() //現在時刻を取得する
fmt.Printf("current time:%v\n", now)
year := now.Year() //年
month := now.Month() //月
day := now.Day() //日
hour := now.Hour() //時間
minute := now.Minute() //分
second := now.Second() //秒
fmt.Printf("%d-%02d-%02d %02d:%02d:%02d\n", year, month, day, hour, minute, second)
}
操作の結果は次のようになります。
current time:2023-05-18 12:33:19.4712277 +0900 CST m=+0.006980401
2023-05-18 12:33:19
2) タイムスタンプを取得する
タイムスタンプは、1970 年 1 月 1 日 (08:00:00GMT) から現在時刻までの合計ミリ秒数であり、Unix タイムスタンプ (UnixTimestamp) とも呼ばれます。
時刻オブジェクトに基づいてタイムスタンプを取得するサンプル コードは次のとおりです。
package main
import (
"fmt"
"time"
)
func main() {
now := time.Now() //現在時刻の取得
timestamp1 := now.Unix() //タイムスタンプ
timestamp2 := now.UnixNano() //ナノ秒タイムスタンプ
fmt.Printf("現在のタイムスタンプ:%v\n", timestamp1)
fmt.Printf("現在のナノ秒タイムスタンプ:%v\n", timestamp2)
}
time.Unix() 関数を使用してタイムスタンプを時刻形式に変換します。サンプルコードは次のとおりです。
package main
import (
"fmt"
"time"
)
func main() {
now:= time.Now() //現在時刻を取得
timestamp:= now.Unix() //タイムスタンプ
timeObj:= time.Unix(timestamp、0) //タイムスタンプを時間形式に変換する
fmt.Println(timeObj)
year:= timeObj.Year() //年
month:= timeObj.Month() //月
day:= timeObj.Day() //日
hour:= timeObj.Hour() //時間
minute:= timeObj.Minute() //分
second:= timeObj.Second() //秒
fmt.Printf("%d-%02d-%02d %02d:%02d:%02d \n"、year、month、day、hour、minute、second)
}
操作の結果は次のようになります。
2023-05-18 13:24:09 +0900 JST
2023-05-18 13:24:09
3) 現在の曜日を取得する
time パッケージの Weekday 関数は、特定の時点に対応する曜日を返すことができます。サンプル コードは次のとおりです。
package main
import (
"fmt"
"time"
)
func main() {
//タイムスタンプ
t := time.Now()
fmt.Println(t.Weekday().String())
}
操作の結果は次のようになります。
Thursday
時間操作機能
1) 追加
日々の開発プロセスでは、特定の時間 + 時間間隔などの要件に遭遇することがありますが、Go 言語の Add メソッドは次のとおりです。
func (t Time) Add(d Duration) Time
Add 関数は、時点 t + 時間間隔 d の値を返すことができます。
【例】1時間後の時刻を求める:
package main
import (
"fmt"
"time"
)
func main() {
now := time.Now()
later := now.Add(time.Hour) // 現在時刻に1時間を加えた時刻
fmt.Println(later)
}
操作の結果は次のようになります。
2019-12-12 16:00:29.9866943 +0800 CST m=+3600.007978201
2) サブ
2 つの時間の差を求めます。
func (t Time) Sub(u Time) Duration
期間 t ~ u の値を返します。結果が、Duration が表現できる最大値または最小値を超える場合は、最大値または最小値が返されます。時点 t – d (d はDuration) を取得するには、t.Add(-d) を使用します。
3) 等しい
2 つの時間が同じかどうかを判断します。
func (t Time) Equal(u Time) bool
Equal 関数はタイム ゾーンの影響を考慮するため、異なるタイム ゾーン標準の時刻も正しく比較できます。Equal メソッドは、t==u を使用するのとは異なります。Equal メソッドは、場所とタイム ゾーンの情報も比較します。
4) 前
ある時点が別の時点より前であるかどうかを判断します。
func (t Time) Before(u Time) bool
t が u より前の時点を表す場合は true、それ以外の場合は false を返します。
5) 後
ある時点が別の時点より後であるかどうかを判断します。
func (t Time) After(u Time) bool
t が u 以降の時点を表す場合は true を返し、それ以外の場合は false を返します。
タイマー
time.Tick(時間間隔) を使用してタイマーを設定します。タイマーは本質的にチャネルです。サンプル コードは次のとおりです。
package main
import (
"fmt"
"time"
)
func main() {
ticker := time.Tick(time.Second) //1秒間隔のタイマーを定義する
for i := range ticker {
fmt.Println(i) //毎秒実行されるタスク
}
}
時間の書式設定
時刻型には書式設定用の Format メソッドが組み込まれています。Go 言語で書式設定された時刻テンプレートは一般的なYmd H:M:S
ではなく、Go 言語の誕生時刻である 15:04 を使用することに注意してください。 2006年1月2日分05秒。
ヒント: 時刻を 12 時間形式に設定する場合は、PM を指定する必要があります。
package main
import (
「fmt」
「time」
)
main() {
now:= time.Now()
//フォーマットテンプレートは、Goの誕生日2006年1月2日15時04分Mon Janです。
//24時間制
fmt.Println(now.Format("2006-01-02 15:04:05.000 Mon Jan"))
//12時間制
fmt.Println(now.Format("2006-01-02 03:04:05.000 PM Mon Jan"))
fmt.Println(now.Format("2006/01/02 15:04"))
fmt.Println(now.Format("15:04 2006/01/02"))
fmt.Println(now.Format("2006/01/02"))
}
Parse 関数は、フォーマットされた時刻文字列を解析し、それが表す時刻を返すことができます。
func Parse(layout, value string) (Time, error)
Parse 関数に似ているのは、ParseInLocation 関数です。
func ParseInLocation(layout, value string, loc *Location) (Time, error)
ParseInLocation は Parse 関数に似ていますが、次の 2 つの重要な違いがあります。
- まず、タイム ゾーン情報が欠落している場合、Parse は時刻を UTC 時間として解釈し、ParseInLocation は戻り値の Location を loc に設定します。
- 次に、時刻文字列がタイム ゾーン オフセット情報を提供する場合、Parse はローカル タイム ゾーンとの一致を試みますが、ParseInLocation は loc と一致します。
サンプルコードは次のとおりです。
package main
import(
"fmt"
"time"
)
func main(){
var layout string = "2006-01-02 15:04:05"
var timeStr string = "2023-05-18 15:22:12"
timeObj1, _ := time.Parse(layout, timeStr)
fmt.Println(timeObj1)
timeObj2, _ := time.ParseInLocation(layout, timeStr, time.Local)
fmt.Println(timeObj2)
}