谢谢。
进一步解释:我使用的日期库在创建具有未来日期和时区的对象时非常缓慢。结果发现它在进行线性计算以计算日期是否处于夏令时。不仅如此,它也是在对象创建时执行这项工作的。显然,它可以等到被询问时再执行此操作,但它也应该更加高效。
当然,DST规则会发生变化,日期库无法预测未来,但另一种选择是对本地化日期设置任意上限。
大家已经谈论了始终变化的夏令时存在的问题。但我可以接受这样的前提,我们假装当前已知的规则将永远适用。
要获取您的夏令时信息,首先要做的是计算未来日期的年/月/日(如果它不是以该形式表示的)。然后查找您的时区并提取相对于UTC的变化、夏令时开/关规则和偏移量。根据您的“目标”年份可能会有几种不同的规则,要确保抓住正确的规则。由于下面解释的原因,也可能很方便了解前一年的规则。
开/关规则将具有类似于“Oct lastSun”这样奇怪的规格:这意味着在十月最后一个星期天的晚上切换发生。
您需要做的是收集所有这些简洁格式的“规则”,并为每个规则开发一些代码,以确定该规则指示的最后一个日期。现在是十二月,所以给定像“3月最后一个星期天”和“10月最后一个星期天”这样的规则,我的时区会有这些日期: 2009年3月29日和2009年10月25日。这些日期中哪个更近?十月。十月与“关闭”相关,因此我们目前没有夏令时。
无论目标日期是在夏令时开始或结束日期之前还是之后,您都可以计算当前(即目标)年份的夏令时开启/关闭日期;如果开启/关闭日期在目标日期的未来,则只需再次为上一年进行规则计算。请注意,规则可能在此期间发生了变化,因此请确保应用于您正在查看的年份的正确规则。
最坏情况下,您需要为上一年重复两次规则计算。但除此之外,没有其他搜索,因此它严格是O(1)。
我在这里找到了一个本地/夏令时/时区计算器:http://home-4.tiscali.nl/~t876506/WhatDay.html,由于它是JavaScript小程序,您应该能够轻松地借鉴代码。不过它并不能处理所有规则,因此您需要添加一些代码以处理剩余规则。
更新:我刚刚注意到你的时间中有小时和分钟。这会稍微复杂一些。如果你的日期不是在“切换”日期上,那么我上面给出的指示就可以了。否则,你需要考虑时间。我想最干净的做法是在确定“最近”的时候包括时间。也就是说,如果你的目标时间是00:30 UTC,而给定时区的切换时间是01:00,那么目标年份的切换时间仍然在未来,你必须使用前一年的切换时间。实际上,这意味着“其他”切换时间是最近的,它的开/关状态适用。
你最大的问题是由当地政府制定的夏令时规则。政府可以随时通过几乎任何法律,因此改变规则的方式是你无法预测的。
嗯,我认为问题的关键是确定一个未来很远的日期的星期几。
为此,我建议采用以下方法:
wday = (ref_day + 2 *(int)((target_year - ref_year)/ 400))mod 7
在您获得该年1月1日的星期后,您可以像Carl Smotricz所写的那样计算夏令时切换日期。