web-dev-qa-db-ja.com

GoでUTCを「現地時間」に変換する

UTC時間を現地時間に変換するにはどうすればよいですか?

現地時間を必要とするすべての国のUTC差を使用してマップを作成しました。次に、その差を現在の時間(UTC)に期間として追加し、それがその特定の国の現地時間であることを期待して結果を出力します。

何らかの理由で結果が間違っています。たとえば、 ハンガリー の場合、1時間の差があります。間違った結果が得られる理由は何ですか?

package main

import "fmt"
import "time"

func main() {

    m := make(map[string]string)
    m["Hungary"] = "+01.00h"

    offSet, err := time.ParseDuration(m["Hungary"])
    if err != nil {
        panic(err)
    }
    t := time.Now().UTC().Add(offSet)
    Nice := t.Format("15:04")

    fmt.Println(Nice)
}
17
hey

遊び場の時間は2009-11-10 23:00:00 +0000 UTCに設定されているため、機能していることに注意してください。

適切な方法はtime.LoadLocationを使用することですが、以下に例を示します。

var countryTz = map[string]string{
    "Hungary": "Europe/Budapest",
    "Egypt":   "Africa/Cairo",
}

func timeIn(name string) time.Time {
    loc, err := time.LoadLocation(countryTz[name])
    if err != nil {
        panic(err)
    }
    return time.Now().In(loc)
}

func main() {
    utc := time.Now().UTC().Format("15:04")
    hun := timeIn("Hungary").Format("15:04")
    eg := timeIn("Egypt").Format("15:04")
    fmt.Println(utc, hun, eg)
}
25
OneOfOne

あなたのアプローチには欠陥があります。 1つの国には、たとえば米国とロシアなど、複数のタイムゾーンを設定できます。夏時間(DST)のため、タイムゾーンは、たとえばハンガリーなど、複数の時間を持つことができます。ハンガリーはUTC +1:00であり、DSTでもUTC + 2:00です。

指定されたUTC時間の現地時間を使用する各場所に対して、IANA(tzdata)タイムゾーンの場所を使用します。例えば、

package main

import (
    "fmt"
    "time"
)

func main() {
    utc := time.Now().UTC()
    fmt.Println(utc)
    local := utc
    location, err := time.LoadLocation("Europe/Budapest")
    if err == nil {
        local = local.In(location)
    }
    fmt.Println("UTC", utc.Format("15:04"), local.Location(), local.Format("15:04"))
    local = utc
    location, err = time.LoadLocation("America/Los_Angeles")
    if err == nil {
        local = local.In(location)
    }
    fmt.Println("UTC", utc.Format("15:04"), local.Location(), local.Format("15:04"))
}

出力:

2014-08-14 23:57:09.151377514 +0000 UTC
UTC 23:57 Europe/Budapest 01:57
UTC 23:57 America/Los_Angeles 16:57

参照:

IANAタイムゾーンデータベース

tzデータベース

tzデータベースタイムゾーン

タイムゾーン

ハンガリーの時間

12
peterSO

特定のゾーンをいじる手間を省き、ロケーション「ローカル」を使用します。ローカルおよびUTC変換の完全で実用的な例を次に示します。

package main

import (
    "fmt"
    "log"
    "time"
)

const (
    dateTimeFormat = "2006-01-02 15:04 MST"
    dateFormat    = "2006-01-02"
    timeFormat    = "15:04"
)

// A full cycle example of receiving local date and time,
// handing off to a database, retrieving as UTC, and formatting as local datetime
// This should be good in *any* timezone
func main() {
    // If using a form for entry, I strongly suggest a controlled format input like
    // <input type="date" ... > and <input type="time" ... >
    locallyEnteredDate := "2017-07-16"
    locallyEnteredTime := "14:00"

    // Build a time object from received fields (time objects include zone info)
    // We are assuming the code is running on a server that is in the same zone as the current user
    zone, _ := time.Now().Zone() // get the local zone
    dateTimeZ := locallyEnteredDate + " " + locallyEnteredTime + " " + zone
    dte, err := time.Parse(dateTimeFormat, dateTimeZ)
    if err != nil {
        log.Fatal("Error parsing entered datetime", err)
    }
    fmt.Println("dte:", dte) // dte is a legit time object
    // Perhaps we are saving this in a database.
    // A good database driver should save the time object as UTC in a time with zone field,
    // and return a time object with UTC as zone.

    // For the sake of this example, let's assume an object identical to `dte` is returned
    // dte := ReceiveFromDatabase()

    // Convert received date to local.
    // Note the use of the convenient "Local" location https://golang.org/pkg/time/#LoadLocation.
    localLoc, err := time.LoadLocation("Local")
    if err != nil {
        log.Fatal(`Failed to load location "Local"`)
    }
    localDateTime := dte.In(localLoc)

    fmt.Println("Date:", localDateTime.Format(dateFormat))
    fmt.Println("Time:", localDateTime.Format(timeFormat))
}
2
Rohanthewiz