【问题标题】:Daylight saving and DateTime.AddHour()夏令时和 DateTime.AddHour()
【发布时间】:2017-04-29 20:12:38
【问题描述】:

我对臭名昭著的夏令时有疑问。

我有一个数据点列表,一年中每个小时一个。为了检查是否所有数据点都存在,我创建了一个时间迭代器,如下所示:

DateTime timeIterator = new DateTime(year, 1, 1, 0, 0, 0);

用它迭代

timeIterator = timeIterator.AddHours(1);

如果时间点出现在列表中,则检查每次迭代。

问题出现在夏令时。我以 2014 年为例,时钟在 3 月 30 日从 0200 移动到 0300。所以,在 0159 之后是 0300。但是 DateTime.AddHours() 完全忽略了夏令时。如果 timeIterator 在 {30.03.2014 01:00:00} 并且我调用 AddHours(1) 我得到 {30.03.2014 02:00:00} 这显然不存在。

如果我现在针对这个数据点测试列表,它(自然)不在列表中,我会抛出错误的“丢失数据点错误”。

如何检查我的 DateTime 是否为有效时间点?

提前致谢,
弗兰克

【问题讨论】:

  • 嗯,这真的取决于你说的是哪个国家。
  • 您与this 相关的问题回答了有关TimezoneInfo 的问题。
  • 另请阅读here,搜索验证您的输入!
  • @PatrickHofman 即将发布相同的链接 :-)
  • 大声笑。也谷歌了? @Tho

标签: c# datetime dst


【解决方案1】:

如何检查我的 DateTime 是否为有效时间点?

不要检查,确保它。例如,您可以计算 UTC 小时数并将每个点转换为本地时间。

DateTimeOffset timeIterator = new DateTimeOffset(new DateTime(year, 1, 1, 0, 0, 0, DateTimeKind.Local));
timeIterator = timeIterator.AddHours(1);
timeIterator.LocalDateTime;

// assuming you have a TimeZoneInfo object, you can also get different local times:
TimeZoneInfo tzi = /* the timezone */;
TimeZoneInfo.ConvertTimeFromUtc(timeIterator.UtcDateTime, tzi);

但是,正如 Damien_The_Unbeliever 所评论的,这只能解决问题的一部分,程序将不再检查是否存在无效日期。当您的数据以当地时间存储时,会出现一个不同的问题。这意味着从 DST 到正常时间的转换将有两个连续的小时,具有相同的本地 DateTime 表示。为了避免这种情况,数据必须与完整的信息(UTC 或显式偏移)一起存储,以便以后进行比较。

编辑:

如果您的数据时区有一个有效的TimeZoneInfo 对象,并且由于某种原因不想切换到DateTimeOffset,您还可以使用以下函数:

TimeZoneInfo tzi = /* the timezone */;
DateTime timeIterator = /* the time */;
if (tzi.IsAmbiguousTime(timeIterator))
{
    /* Expect multiple data entries */
}
if (tzi.IsInvalidTime(timeIterator))
{
    /* Expect no data entries */
}

【讨论】:

  • 问题是,如果他们继续将日期存储为当地时间,他们将不会发现他们在一年中的另一个转换点是否缺少信息。例如。如果数据存储为 0100 UTC、0200 UTC 和 0400 UTC,但在 0300 UTC 时钟被调回,它们将在本地时间 0100、0200 和 0300 有数据,但它们实际上缺少应该在0300 UTC 也映射到本地时间 0200,他们仍然不会在这里找到它。
  • @Damien_The_Unbeliever 真实故事。如果问题作者没有检查外部数据(没有影响),那么肯定是时候改进日期时间存储了。但是,如果任务是检查现有的历史数据,那么损坏已经完成,无法再通过值比较来区分双倍。我想我必须编辑我的问题以澄清一些事情。
  • 大家好,我检查了外部数据——我的问题是,我最终(夏令时)检查了一个无效的日期。关键是:我必须知道时区以避免这种情况,否则我无法知道这是否是有效日期。我想我会切换到 NodaTime 以更有意识地处理它......
  • @Aaginor 如果您检查客户端时区中的数据,我使用DateTimeOffsetLocalDateTime 的解决方案应该适合您(DateTimeOffset.AddHours(1) 将使本地时间增加02 小时在 DST 转换点上,这与 DateTime 行为不同)。否则,请在有关您所需时区的问题上更准确,应该很容易采用该解决方案。
  • 嘿,grek,您对答案的编辑几乎就是我现在所做的。客户端时区对我来说不够“节省”,因为他加载的数据可能来自另一个时区。所以他需要告诉我,这些数据来自哪个时区。切换到 DataTimeOffset 将是一个选项,但如果我切换(由于项目时间限制,现在我只是在做肮脏的快速黑客)我会切换到 NodaTime。
【解决方案2】:

我也遇到了时区问题。 我建议您将日期保存为 UTC 值

然后改造它:(可能使用扩展方法)

private DateTime TransformToTimezone(DateTime datetime)
{
            TimeZoneInfo beZone = TimeZoneInfo.FindSystemTimeZoneById("Romance Standard Time");

            //Convert to timezone
            return TimeZoneInfo.ConvertTimeFromUtc(datetime, beZone);
}

【讨论】:

  • 是的,或者用我的数据存储时区(我可能会这样做)。 ...并使用 NodaTime 让这更加清晰和透明。
猜你喜欢
  • 2012-10-23
  • 2016-02-02
  • 2010-09-19
  • 2016-10-11
  • 2021-06-22
  • 2014-02-22
  • 2019-04-09
  • 1970-01-01
  • 2013-10-13
相关资源
最近更新 更多