使用TimeZoneInfo类来计算夏令时的时间变化

时间:2012-11-08 16:16:11

标签: c# .net timezone console-application dst

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

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();
        }
    }

不幸的是,这是打印出来的: enter image description here

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

修改 我现在的时区是东部。

2 个答案:

答案 0 :(得分: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行为匹配的时区。

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

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

答案 1 :(得分:1)

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

我认为这解释了它:

Daylight Saving Time

“在20世纪60年代早期,遵守夏令时非常不一致,有大量的时间观察,并且没有就何时更换时钟达成一致。”

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

相关问题