野田时间:如何表示"standard time"

noda time: how to represent "standard time"

我从一个文本文件中接收数据,其中的日期通常是 "standard time"(例如中部标准时间或东部标准时间。我的意思是 没有观察到夏令时调整).使用 Noda Time,我试图找出表示这一点的最佳方式。

我的第一个想法是我应该为此制作一个 DateTimeZone。我注意到一些 "standard time" 时区包含在 tz 数据库中(例如,"America/Cancun" 可以用于东部标准时间),但其他时区似乎没有任何东西可以代表它们 "standard time" 数据库中的变体。

然后我想我应该制作一个 Offset,或者直接从 Offset 制作一个 DateTimeZone,但我似乎无法找到获取 DateTimeZone 的基本偏移量的方法。对于美国大陆的时区,我很确定我可以做 DateTimeZone.ForOffset(localTimeZone.MinOffset)(其中 localTimeZone 是 DateTimeZone),但我非常怀疑这是否适用于一些更奇怪的时区。我也试过 DateTimeZone.ForOffset(localTimeZone.GetZoneInterval(SystemClock.Instance.GetCurrentInstant()).StandardOffset) 但这太迂回了,我怀疑这是不正确的原因。

可以只存储与每个文件提供者关联的原始偏移量,但是如果配置说它是在中央标准时间而不是它说的话,配置应用程序会容易得多它的偏移量为 -6。

我是否缺少执行此操作的方法?还是我对问题的概念化有问题,以至于这不是正确的方法?

DateTimeZone 不一定只有一个 "base offset"。它会随着时间的推移而改变。例如,阿拉斯加大部分地区的标准时间在 1983 年从 UTC-10 更改为 UTC-9。

现在 可能 对于您感兴趣的时区不是问题...在这种情况下,您可以使用 "find the standard offset for the local time zone at the current instant, then create a constant-offset DateTimeZone from that" 的方法。我可能会使用三个语句而不是您当前的巨型表达式,但它会做您想要的。

如果您想要一个等同于现有时区的时区,包括对其标准偏移量的任何更改,但没有任何夏令时,则很难实现。 可以完成,但不会非常简单。您可能希望自己的 DateTimeZone 子类接受现有的 DateTimeZone 并从时间开始迭代所有 ZoneInterval 值直到某个合适的终点(例如 2200,作为远-之后很长一段时间内不会指定任何规则更改的未来日期)并计算出您的 new ZoneInterval 值。如果你愿意,我可以提供一个示例实现,但你真的想首先考虑它是否是你想要的...

这里有一些代码可以向您展示在 1930 年到 2100 年之间的某个时间点更改了标准偏移量的所有时区 - 显然您可以轻松更改时间间隔以更改标准以更紧密地匹配您的上下文。

using System;
using System.Linq;
using NodaTime;
using NodaTime.Extensions;

class Test
{
    static void Main()
    {
        Instant min = Instant.FromUtc(1930, 1, 1, 0, 0, 0);
        Instant max = Instant.FromUtc(2100, 1, 1, 0, 0, 0);

        foreach (var zone in DateTimeZoneProviders.Tzdb.GetAllZones())
        {
            var initialStandard = zone.GetZoneInterval(min).StandardOffset;
            var zoneIntervals = zone.GetZoneIntervals(min, max);
            var firstChange = zoneIntervals.FirstOrDefault(zi => zi.StandardOffset != initialStandard);
            if (firstChange != null)
            {
                Console.WriteLine(zone.Id);
                Console.WriteLine($"Initial standard offset: {initialStandard}");
                Console.WriteLine($"First different standard offset: {firstChange}");
                Console.WriteLine();
            }
        }
    }
}