Golang中的夏令时节约时间

8

我一直在设计一个调度接口的 UI,用户可以设置一定数量的小时后的定时器。如果可能的话,我希望能够处理夏令时问题,但我认为这应该很简单。然而,在研究 Golang 包中的 time.Time 时,我遇到了以下不一致性(如果这就是它的问题所在的话)。

package main

import (
   "fmt"
   "time"
)

    func main(){
        const timeFormat = "2 Jan, 2006 3:04pm (MST)"
        test , err := time.Parse( timeFormat, "25 Oct, 2015 1:59am (BST)" )
        fmt.Println( test , test.UTC() , err)
        dur , _ := time.ParseDuration( "1m" )
        test = test.Add( dur )
        fmt.Println( test , test.UTC())

        fmt.Println( "--------------------"  )

        test , err = time.Parse( timeFormat, "25 Oct, 2015 2:01am (BST)" )
        fmt.Println( test , test.UTC() , err)
        test = test.Add( dur )
        fmt.Println( test , test.UTC())

        test = test.Sub( dur )
        fmt.Println( test , test.UTC())
     }   

我知道2015年10月25日英国夏令时在凌晨2点结束,时钟会被调回到格林威治标准时间(UTC)的1点。如果我将凌晨1:59的英国夏令时增加一分钟,时间确实会切换到GMT。

2015-10-25 01:59:00 +0100 BST 2015-10-25 00:59:00 +0000 UTC <nil>
2015-10-25 01:00:00 +0000 GMT 2015-10-25 01:00:00 +0000 UTC
--------------------
2015-10-25 02:01:00 +0000 BST 2015-10-25 02:01:00 +0000 UTC <nil>
2015-10-25 02:02:00 +0000 BST 2015-10-25 02:02:00 +0000 UTC
然而,如果我在英国夏令时(BST)的2点后解析时间,我希望它能切换到格林威治标准时间(GMT),就像在过渡期间递增时间一样。如果过渡代码是由Add例程调用的,则再添加一分钟,但这也不能将时间恢复到GMT。 我期望以下情况之一发生: a)BST始终保持GMT + 1 b)在BST“无效”的任何时间自动更改为正确的GMT时间(无效BST介于每年10月最后一个星期日的2点和次年3月最后一个星期日的2点之间) c)如果在这些日期中使用BST(以及其他国家/地区的夏令时),则抛出错误。 否则,我必须检查用户是否输入了BST日期,以确定该日期是否在BST之外并进行调整或强制用户使用UTC时间,这有点违背了将夏令时功能内置到库中的初衷。 在研究过程中,我注意到了这个https://www.youtube.com/watch?v=-5wpm-gesOY,并且已经决定它绝对不像我最初想象的那么简单... 欢迎提供任何见解或更好的处理夏令时的方法。 使用Debian Wheezy上的go版本1.0.2进行编辑:重试使用go版本1.3.3并获得此输出。
2015-10-25 01:59:00 +0100 BST 2015-10-25 00:59:00 +0000 UTC <nil>
2015-10-25 01:00:00 +0000 GMT 2015-10-25 01:00:00 +0000 UTC
--------------------
2015-10-25 01:00:00 +0000 GMT 2015-10-25 01:00:00 +0000 UTC <nil>
2015-10-25 01:01:00 +0000 GMT 2015-10-25 01:01:00 +0000 UTC

所以在较新的版本中看起来像我预期的那样工作... 我还发现了这个问题Daylight saving time and time zone best practices,所以我将会认真阅读它。

谢谢。


2
首先,使用当前版本(go1.4.2)的Go:入门指南 - peterSO
我认为使用更新版本的Go是唯一的答案,因为时间和日历通常是一个相当困难的问题,我们应该优先使用标准库函数而不是编写自己的函数。 - Austin Mullins
test.Sub(dur) 不合法,您可能想要使用 test.Add(-dur)。在包含 Go 代码时,提供可工作的playground链接会很有帮助。(附注:请使用 dur := time.Minutedur := 60 * time.Second 等常量而不是使用 time.ParseDuration)。 - Dave C
你是对的。我的剪切和粘贴中,test.Sub调用被删除了,它本来不应该在那里...谢谢。 - hairy_marmite
谢谢大家,我刚刚检查了一下使用的是Go 1.3.3(也已经安装在我的系统上,但Debian仍然默认使用1.0.2)- 根据我的编辑。我将尝试使用1.4并清除所有旧版本。再次感谢。 - hairy_marmite
1个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
18

与其他所有公司不同,Go使用IANA时区数据库,该数据库会定期更新并包含在当前的Go版本中。

你使用的是go1.0.3版本,它发布于2012年3月 (发布历史记录)。英国的时区数据是后来添加的,追溯到2015年。

始终使用最新版本的Go进行时区计算。


4
Go使用IANA格式的数据,但在运行时发现的捆绑版本是最后一种选择,先尝试操作系统中的环境和标准位置。 - SEngstrom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,