代码之家  ›  专栏  ›  技术社区  ›  jbrown

如何在Go中将时间转换到不同的时区?

  •  1
  • jbrown  · 技术社区  · 3 年前

    我正在分析用户发送的时间戳。时间戳是某个位置的本地时间戳,但源字符串没有指定它。服务器端我正在查找该位置的时区,需要将时间转移到该时区,而不更改其显示值。

    我知道我可以这样做,在不同的地点给我同等的时间:

    package main
    
    import (
        "fmt"
        "time"
    )
    
    func main() {
        myTime := time.Now()
        fmt.Println(myTime.Format(time.RFC3339))
        
        loc, err := time.LoadLocation("America/New_York")
        if err != nil {
            panic(err)
        }
        
        fmt.Println(myTime.In(loc).Format(time.RFC3339))
    }
    
    

    这只是打印:

    2009-11-10T23:00:00Z
    2009-11-10T18:00:00-05:00
    

    这不是我想要的。

    我正试图找到一种将时区设置为例如的方法。 America/New_York ,所以我应该得到例如。 2009-11-10T23:00:00-05:00 ,这是原始的当地时间,但应用了纽约偏移量。

    我如何在Go中做到这一点?

    0 回复  |  直到 3 年前
        1
  •  3
  •   blackgreen VonC    3 年前

    这种混乱源于这样一个事实,即直观地出现在脑海中的API In 简单地将同一时间点解释为处于不同的时区。所以当你打印它时,显示不是你想要的。

    要将时区设置为时间戳,同时保持相同的显示值,只需使用 time.Date 具有与原始时间戳和新位置相同的值:

    t := time.Date(myTime.Year(), myTime.Month(), myTime.Day(), myTime.Hour(), myTime.Minute(), myTime.Second(), myTime.Nanosecond(), loc)
    // 2009-11-10T23:00:00-05:00 in the playground
    

    另一个选项是将时间实例设置为新时区,然后使用 Zone() 以获取偏移量,然后从本地化时间中减去以秒为单位的值。

    package main
    
    import (
        "fmt"
        "time"
    )
    
    func main() {
        myTime := time.Now()
        fmt.Println(myTime.Format(time.RFC3339))
        
        loc, err := time.LoadLocation("America/New_York")
        if err != nil {
            panic(err)
        }
    
        locTime := myTime.In(loc)
        _, zoneOffset := locTime.Zone()
        
        inZoneTime := locTime.Add(-time.Duration(zoneOffset) * time.Second)
    
        // handle DST transitions
        if inZoneTime.IsDST() {
            inZoneTime = inZoneTime.Add(1*time.Hour)
        }
        
        fmt.Println(inZoneTime.Format(time.RFC3339))
        // 2009-11-10T23:00:00-05:00
    }
    

    今天要在您的本地机器中测试夏令时转换(假设您所在的国家/地区和我一样),您可以将位置更改为夏令时有效的位置,例如。 Australia/Canberra .

    输入为 time.Now() 无DST进入 澳大利亚/堪培拉 ,上述程序打印以下内容:

    2021-11-12T13:27:33+01:00
    is DST: true
    2021-11-12T13:27:33+11:00
    

    游戏场 https://play.golang.org/p/5qy2tOcIMwn

    推荐文章