如何将UTC时间转换为本地时间?
我已经创建了一个地图,其中包含所有我需要的当地时间的国家的UTC差异。然后,我将该差异作为持续时间添加到当前时间(UTC),并打印结果,希望这是该特定国家的当地时间。
由于某些原因,结果是错误的。比如匈牙利就有一个小时的时差。知道我为什么会得到错误的结果吗?
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)
}
请记住,操场的时间设置为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)
}
你的方法有缺陷。一个国家可以有几个时区,例如,美国和俄罗斯。由于实行夏令时,一个时区可以有多个时间,例如匈牙利。匈牙利是UTC+ 1:00,夏令时也是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数据库数据库时区
时区
匈牙利时间
使用location "Local"来节省使用特定区域的麻烦。以下是本地和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))
}
注意:最好使用你的编辑器而不是go playground。
package main
import (
"fmt"
"time"
)
func main() {
now := time.Now()
location, _ := time.LoadLocation("UTC")
fmt.Printf("UTC time is ------ %sn", now.In(location))
location, _ = time.LoadLocation("Europe/Berlin")
fmt.Printf("Berlin time is ------ %sn", now.In(location))
location, _ = time.LoadLocation("Africa/Casablanca")
fmt.Printf("Casablanca time is ------ %sn", now.In(location))
location, _ = time.LoadLocation("Asia/Dubai")
fmt.Printf("Dubai time is ------ %sn", now.In(location))
}