自分用メモ。
ローカルタイムからUTCに変換
tm, err := time.ParseInLocation("2006-01-02 15:04:05", "2017-03-07 10:00:00", time.Local)
tm.In(time.UTC)
UTCからローカルタイムに変換
tm, err := time.ParseInLocation("2006-01-02 15:04:05", "2017-03-07 10:00:00", time.UTC)
tm.In(time.Local)
現在の時刻をUTCに変換
tm = time.Now()
tm.In(time.Local)
ロケーションの取得
time.Local # ローカルのロケーション
time.UTC # UTC
loc, err := time.LoadLocation("Asia/Tokyo") # Asia/Tokyoのロケーションを取得
LoadLocationのコードリーディング
LoadLocation
はtime/zoneinfo.go
に定義されています。
func LoadLocation(name string) (*Location, error) {
if name == "" || name == "UTC" {
return UTC, nil
}
if name == "Local" {
return Local, nil
}
if zoneinfo != "" {
if z, err := loadZoneFile(zoneinfo, name); err == nil {
z.name = name
return z, nil
}
}
return loadLocation(name)
}
zoneinfo
はZONEINFO環境変数の値になります。値が入っていない場合はloadLocation
を呼び出します。UNIX系列の場合は以下の関数が呼び出されます。
func loadLocation(name string) (*Location, error) {
var firstErr error
for _, zoneDir := range zoneDirs {
if z, err := loadZoneFile(zoneDir, name); err == nil {
z.name = name
return z, nil
} else if firstErr == nil && !isNotExist(err) {
firstErr = err
}
}
if firstErr != nil {
return nil, firstErr
}
return nil, errors.New("unknown time zone " + name)
}
zoneDirs
はtime/zoneinfo_unix.go
で定義されていて、タイムゾーン情報が格納されるディレクトリやzipファイルの配列になります。
// Many systems use /usr/share/zoneinfo, Solaris 2 has
// /usr/share/lib/zoneinfo, IRIX 6 has /usr/lib/locale/TZ.
var zoneDirs = []string{
"/usr/share/zoneinfo/",
"/usr/share/lib/zoneinfo/",
"/usr/lib/locale/TZ/",
runtime.GOROOT() + "/lib/time/zoneinfo.zip",
}
loadZoneFile
ではzoneinfoディレクトリとロケーション名が引数で渡されます。
func loadZoneFile(dir, name string) (l *Location, err error) {
if len(dir) > 4 && dir[len(dir)-4:] == ".zip" {
return loadZoneZip(dir, name)
}
if dir != "" {
name = dir + "/" + name
}
buf, err := readFile(name)
if err != nil {
return
}
return loadZoneData(buf)
}
ディレクトリ名+指定したタイムゾーンのファイル名(i.g. “Asia/Tokyo”)でファイルを検索し、ファイルが存在すればタイムゾーン情報ファイルをloadZoneData
で読み出して、Location構造体に格納します。