3

我有一些过时的代码试图解释夏令时引起的时间变化,如下所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            for (int i = 1; i <= 31; i++)
            {
                DateTime dt = new DateTime(1960, 3, i, 0, 0, 0);
                Console.WriteLine(dt.ToUniversalTime());
            }

            Console.WriteLine();

            for (int i = 1; i <= 30; i++)
            {
                DateTime dt = new DateTime(1960, 4, i, 0, 0, 0);
                Console.WriteLine(dt.ToUniversalTime());
            }

            Console.ReadKey();
        }
    }
}

此代码遍历 1960 年 3 月和 4 月的日子并打印日期时间。但是,这并不能正确解释 1960 年的时间变化,我相信因为当时时间变化的日期不同。我试图使用 TimeZoneInfo 类来解决这个问题。我将代码更改为以下内容:

class Program
    {
        static void Main(string[] args)
        {
            for (int i = 1; i <= 31; i++)
            {
                DateTime dt = new DateTime(1960, 3, i, 0, 0, 0);
                var tz = TimeZoneInfo.Local;
                var utcOffset = new DateTimeOffset(dt, TimeSpan.Zero);
                //use timeZoneInfo class to account for dlst offset
                Console.WriteLine(utcOffset.ToOffset(tz.GetUtcOffset(utcOffset)));
            }

            Console.WriteLine();

            for (int i = 1; i <= 30; i++)
            {
                DateTime dt = new DateTime(1960, 4, i, 0, 0, 0);
                var tz = TimeZoneInfo.Local;
                var utcOffset = new DateTimeOffset(dt, TimeSpan.Zero);
                //use timeZoneInfo class to account for dlst offset
                Console.WriteLine(utcOffset.ToOffset(tz.GetUtcOffset(utcOffset)));

            }

            Console.ReadKey();
        }
    }

不幸的是,这是打印出来的: 在此处输入图像描述

这表明夏令时在 4 月 3 日下午 4 点发生变化,而它应该在 4 月 24 日凌晨 2:00 切换到正确解释夏令时我错过了什么?

编辑: 我当前的时区是东部。

4

2 回答 2

2

看起来 Windows 时区信息与我通过 TZDB 所期望的不匹配。这是一个使用Noda Time的程序来显示 ~1960 和 1965 之间的所有转换,其中包含 BCL TimeZoneInfo(已包装)和 TZDB 2012i 数据:

using System;
using NodaTime;

class Test
{
    static void Main()
    {
        var bcl = DateTimeZoneProviders.Bcl["Eastern Standard Time"];
        var tzdb = DateTimeZoneProviders.Tzdb["America/New_York"];

        ShowTransitions(bcl);
        ShowTransitions(tzdb);
    }

    static void ShowTransitions(DateTimeZone zone)
    {
        Console.WriteLine("Transitions for {0}", zone.Id);
        Instant start = Instant.FromUtc(1960, 1, 1, 0, 0);
        Instant end = Instant.FromUtc(1965, 1, 1, 0, 0);
        var interval = zone.GetZoneInterval(start);
        while (interval.Start < end)
        {
            Console.WriteLine(interval.Start);
            interval = zone.GetZoneInterval(interval.End);
        }
        Console.WriteLine();
    }
}

输出:

Transitions for Eastern Standard Time
1959-10-25T06:00:00Z
1960-04-03T07:00:00Z
1960-10-30T06:00:00Z
1961-04-02T07:00:00Z
1961-10-29T06:00:00Z
1962-04-01T07:00:00Z
1962-10-28T06:00:00Z
1963-04-07T07:00:00Z
1963-10-27T06:00:00Z
1964-04-05T07:00:00Z
1964-10-25T06:00:00Z

Transitions for America/Toronto
1959-10-25T06:00:00Z
1960-04-24T07:00:00Z
1960-10-30T06:00:00Z
1961-04-30T07:00:00Z
1961-10-29T06:00:00Z
1962-04-29T07:00:00Z
1962-10-28T06:00:00Z
1963-04-28T07:00:00Z
1963-10-27T06:00:00Z
1964-04-26T07:00:00Z
1964-10-25T06:00:00Z

还有其他时区 ID 映射到“东部标准时间”,但我没有找到任何与 Windows 行为匹配的时区 ID。

我不认为这是一个TimeZoneInfo错误 - 我相信这是底层 Windows 时区数据中的一个潜在问题。

如果你想匹配 TZDB 数据,当然,你可以使用 Noda Time :)

于 2012-11-08T17:25:56.430 回答
1

有一个 dt.IsDaylightSavingTime()。1960 年对我来说,它会在 4/4 发生变化(比你晚一天),但我是 CST。对于 2012 年,它在我的系统上是正确的。这可能是一个错误。可能只是那一年或直到 X 的所有年份。

我认为这解释了它:

夏令时

“在 1960 年代初期,夏令时的遵守情况非常不一致,时间遵守情况大杂烩,并且没有就何时更换时钟达成一致。”

“1966 年统一时间法案在整个美国建立了一个统一的(在每个时区内)夏令时系统”

于 2012-11-08T16:57:56.350 回答