首页 > 解决方案 > 在 C# 中将时间数据转换为本地时间

问题描述

我已经阅读了一些关于类似主题的帖子,但似乎没有任何内容可以回答这个问题。我的数据库有以下关于时间的信息

该数据代表营业时间。所以每天都有时间。我想在用户当地时间显示该时间,并假设每一天都在未来

int dayOffset = availability.Day - (int)now.DayOfWeek
if (dayOffset < 0)
    dayOffset += 7;

当一个时区可能正在观察 DST 而另一个时区可能确实观察到 DST 但还没有时,我真的很难理解时区和处理。我目前的主要问题是我认为我需要DateTimeOffset为非本地时间创建一个对象,但我不知道该怎么做,因为我不知道 DST 是否生效。我希望我清楚自己。使用日期和时间真的是一种令人费解的体验!

标签: c#datetimedatetimeoffset

解决方案


如其他答案所示,DateTime跨时区处理的通常解决方案是存储 UTC 时间。

但是,考虑到您不是引用特定日期的绝对时间,而是引用特定时区中无限天的时间;将时间存储为 UTC 时间不再有意义,因为由于 DST,UTC 时间(即使我们丢弃日期)会因日期而异。

存储时间的最佳方式与您已经完成的非常接近。

您的问题是您目前存储的时区信息不明确,因为它不是指特定的时区,而是指时区的属性

要解决此问题,只需存储时区标识符而不是 UTC 偏移量和 DST 布尔值。

现在我们可以DateTime使用TimeZoneInfo 类构造对象并将其转换为任何时区:

int dayOffset = availability.Day - (int)DateTime.Today.DayOfWeek;
if (dayOffset < 0)
{
    dayOffset += 7;
}

var openingHourStart = DateTime
                       .SpecifyKind(DateTime.Today, DateTimeKind.Unspecified)
                       .AddDays(dayOffset)
                       .AddMilliseconds(availability.Time);

var sourceTimeZone = TimeZoneInfo.FindSystemTimeZoneById(availability.TimeZoneId);
var userTimeZone = TimeZoneInfo.Local;

var convertedOpeningHourStart = TimeZoneInfo.ConvertTime(openingHourStart,
                                                         sourceTimeZone,
                                                         userTimeZone);

推荐阅读