2017-04-02

golangのtimeライブラリでタイムゾーン変換

自分用メモ。

ローカルタイムから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のコードリーディング

LoadLocationtime/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)
}

zoneDirstime/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構造体に格納します。

このエントリーをはてなブックマークに追加