【问题标题】:TimeZoneInfo incrementing the timezone an hour early on Nov 2nd 2014 EST 2 AMTimeZoneInfo 在 2014 年 11 月 2 日美国东部标准时间凌晨 2 点提前一小时增加时区
【发布时间】:2014-05-07 03:59:33
【问题描述】:

以下是我使用的接受三个输入的方法:

dateTimeInput 是一个代表日期的字符串。

inputFormat 是我的格式字符串,格式如下:yyyy-MM-dd'T'HH:mm:sszzz

timeZoneStandardName 是从 var TimeZoneList = TimeZoneInfo.GetSystemTimeZones(); 检索的唯一时区标识符,其中 ID 是通过 timeZoneList.Id 检索的。

我主要使用TimeZoneInfo 来获取我的小时和分钟偏移量,因为它非常明确它是哪个城市/时区,例如UTC 是输入字符串。

public string unixTimeToDateTime(int unixInput, string outputFormat, string timeZoneStandardName)
{
    // output format is "yyyy-MM-dd'T'HH:mm:sszzz"
    TimeZoneInfo objTimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(timeZoneStandardName);

    if (outputFormat == "yyyy-MM-dd'T'HH:mm:sszzz")
    {
        DateTime UTCDate = Epoch.AddSeconds(unixInput);
        DateTime localDate = TimeZoneInfo.ConvertTimeFromUtc(UTCDate, objTimeZoneInfo);
        return localDate.ToString("yyyy-MM-dd'T'HH:mm:ss") + toTimeSpan(objTimeZoneInfo.GetUtcOffset(localDate).Hours, objTimeZoneInfo.GetUtcOffset(localDate).Minutes);
    }
    // output format is anything else
    else
    {
        DateTime UTCDate = Epoch.AddSeconds(unixInput);
        DateTime localDate = TimeZoneInfo.ConvertTimeFromUtc(UTCDate, objTimeZoneInfo);
        return localDate.ToString(outputFormat);
    }
}

在 Grasshopper 3D 中的组件上使用此方法我将向您展示三个示例:

2014 年 3 月 9 日更改夏令时

2014 年 11 月 2 日(这是我遇到问题的日期)的 DST 更改之一

另一个日期是 2015 年 11 月 2 日,以证明奇怪的差异。


输入 UTC 时间列表(在 2014 年 3 月 9 日强制执行 DST 偏移的战略位置),并将它们输出到 EST 时间,此示例成功输出正确的 DST 偏移,如最右侧面板所示(提示:2014-03-09T01:00:00-05:002014-03-09T03:00:00-04:00)。


现在是奇怪的部分。

如果我进行 2014 年 11 月 2 日 DST 更改,输出如下:

您可以在最右侧的面板上看到,01:00:00-05:00 存在两次。所需的输出应该从01:00:00-04:0001:00:00-05:00


作为比较,这里是 2015 年 11 月 2 日:

2015 年 11 月 2 日(虽然不是年份,但具有相同的 DAYS)在不重复一个小时的情况下切换 DST 没有问题。


所以我的结论是,对于 2014 年 11 月 2 日,DST 提前一个小时增加。

这是DateTimeInfo 的错误吗?为什么过早增加一个小时?是我的代码吗?什么给了?!


编辑:

使用 Unix 时间戳并将其转换为 DateTime:

1414904400Sun, 02 Nov 2014 05:00:00 GMT

1414908000Sun, 02 Nov 2014 06:00:00 GMT

【问题讨论】:

  • 凌晨 1 点到凌晨 2 点在 2014 年 11 月 2 日出现两次,因此该时间出现两次是有道理的。你确定你的结果不正确吗?
  • 如果这是真的,2015 年 11 月 2 日的示例不会做同样的事情吗?我提供这个例子是因为我认为它也是正确的,但它没有意义,因为 UTC 从不重复。
  • 没有。 2015 年 11 月 2 日不是 2015 年的“回退”日期,而是 11 月 1 日。
  • 正确,但 22:00:00-04:0022:00:00-05:00 在转换为 UTC 01:00:00-05:00 和 01:00:00-05:00 重复。
  • 是的,UTC 时间不会重复,但本地时间会重复(您正在将 UTC 时间 转换为 本地时间吗?)。您正在转换两个 UTC 时间,而这两个时间恰好都转换为 2014 年 11 月 2 日凌晨 1 点。这不会发生在 2015 年 11 月 2 日,因为 DST 切换时间不是当天凌晨 1 点。

标签: c# datetime time timezone


【解决方案1】:

在您的代码中,您有:

objTimeZoneInfo.GetUtcOffset(localDate)

试试吧:

objTimeZoneInfo.GetUtcOffset(UTCDate)

来自the remarks on MSDN(强调我的):

如果 dateTime 参数的 Kind 属性与时区对象不对应,则此方法在返回结果之前执行必要的转换。例如,如果 Kind 属性是 DateTimeKind.Local 但时区对象不是本地时区,就会发生这种情况。 如果 dateTime 不明确,或者转换后的时间不明确,此方法会将不明确的时间解释为标准时间。 如果 dateTime 无效,此方法返回 TimeSpan反映 UTC 与时区标准时间之间差异的对象。

【讨论】:

  • 我明天回去工作时会这样做:)。谢谢马特!
  • 这就是答案!!这是否意味着将所有具有objTimeZoneInfo.GetUtcOffset(localDate) 的内容切换为objTimeZoneInfo.GetUtcOffset(UTCDate)
  • 嗨@Matt,最后一个快速问题:puu.sh/7MGWn/cd1d34e528.png 这是我的DateTimeToUnixTime() 方法。此时,它使用localDate 作为objTimeZoneInfo.GetUtcOffset(..) 的输入。根据我的单元测试,我看不到任何差异,但是,为了保持一致,应该使用 result 还是 localDate
  • 举个例子,这里是我对这两种方法的单元测试:puu.sh/7MTB3/4068e06c64.png它到目前为止都通过了。
  • 我不明白你的方法分支的原因。无论格式如何,第一个分支看起来都应该返回。我认为在第二个分支中,您试图通过本地偏移量调整输出整数?如果是这样,您可能不应该这样做。 Unix 时间戳总是以 UTC 表示。
猜你喜欢
  • 2021-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-12
  • 2022-06-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多