这里的情况很棘手。我们的应用程序在一个设置了特定时区(比如说亚洲时间)的系统中运行。但是,客户要求他的应用程序使用欧洲时区运行。
由于我们的数据不是以 UTC 格式存储的,我们是否可以在应用程序中设置区域设置,以便显示的所有日期都使用欧洲时区?我知道我们可以在 Web.Config 中设置文化信息,但我不确定这是否也有助于设置 TimeZone。
顺便说一句,我们的应用程序使用 C# WebForm 和 MSSQL 2008 R2 运行。
您的数据的存储方式与您选择的显示方式完全不同。DateTime
假设日期和时间旨在表示固定时间点(而不是浮动的“本地”时间),我会尝试使用UTC 值编写尽可能多的应用程序。当您检索数据时,如果需要,将其从“存储时区”转换(您尚未说明数据存储在哪个区域),并在存储时将其转换回来。当你显示它时,在你需要的任何时区显示它。
就 .NET 而言,您不需要在全局级别进行设置 - 您可以拥有应用程序范围的配置设置(如果您真的想要)和“帮助”代码,以便在需要显示时对其进行转换。不过,我会非常明确地这样做:当涉及到时间的东西时,你真的不希望隐式地发生转换。
(我还提到我的Noda Time库在日期和时间方面可能会作为一个更清晰的 API 有用。我当然有偏见。如果可以的话,我还建议迁移到以 UTC 存储所有内容。 .. 当然,只有在适当的情况下。)
您应该使用以下方式存储日期DateTimeOffset
:
表示相对于协调世界时 (UTC) 的时间点,通常表示为日期和时间。
使用DateTimeOffset
具有很大的优势,因为这些日期很容易转换为任何时区,而不会丢失事件发生的偏移量(即在某个时刻存储一些数据)。
正如 Jon Skeet 在我的回答中的评论中所建议的那样,时区标识符应该与 一起存储DateTimeOffset
,以便拥有完整的日期+时间信息并使其完全可转换。
另一方面,您可能不会将数据存储在特定时区,而是使用整个时区标识符DateTimeOffset
原样存储,稍后您将根据用户配置文件或应用程序范围的时区将其转换为所需的时区和/ 或应用层中的文化设置。
最后,您可以DateTimeOffset
使用此TimeZoneInfo.ConvertTime(DateTimeOffset, TimeZoneInfo)
重载进行转换。
换个地方怎么样?
CultureInfo currentCulture = Thread.CurrentThread.CurrentCulture;
if (currentCulture.Name != "sv-SE")
{
// Change the current culture to sv-SE and serialize the date.
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("sv-SE");
}
// Do something with a date in swedish timeZone
var swedishNow = DateTime.Now;
// Restore back to the original culture, when finished
Thread.CurrentThread.CurrentCulture = currentCulture;