我有一个网站,是托管在一个不同的时区比用户使用的应用程序。除此之外,用户还可以拥有特定的时区。我想知道其他 SO 用户和应用程序如何处理这个问题?最明显的部分是,在数据库中,日期/时间以 UTC 格式存储。在服务器上时,所有日期/时间都应以 UTC 表示。然而,我看到了三个我正在努力克服的问题:
以 UTC 表示当前时间(使用 DateTime.UtcNow
很容易解决)。
从数据库中提取日期/时间并将其显示给用户。可能存在在不同视图上打印日期的 很多调用。我想在视图和控制器之间的某个层可以解决这个问题。或者在 DateTime
上有一个自定义扩展方法(见下文)。主要的缺点是,在视图中使用日期时间的 每个位置,必须调用扩展方法!
这也会增加使用像 JsonResult
这样的东西的难度。你不能再轻易地调用 Json(myEnumerable)
,它将不得不是 Json(myEnumerable.Select(transformAllDates))
。也许 AutoMapper 可以在这种情况下提供帮助?
从用户获取输入(本地到 UTC)。例如,发布带有日期的表单将需要以前将日期转换为 UTC。我首先想到的是创建一个自定义 ModelBinder
。
下面是我想在视图中使用的扩展:
public static class DateTimeExtensions
{
public static DateTime UtcToLocal(this DateTime source,
TimeZoneInfo localTimeZone)
{
return TimeZoneInfo.ConvertTimeFromUtc(source, localTimeZone);
}
public static DateTime LocalToUtc(this DateTime source,
TimeZoneInfo localTimeZone)
{
source = DateTime.SpecifyKind(source, DateTimeKind.Unspecified);
return TimeZoneInfo.ConvertTimeToUtc(source, localTimeZone);
}
}
我认为处理时区是一件很常见的事情,因为现在很多应用程序都是基于云的,服务器的本地时间可能与预期的时区有很大不同。
这个问题以前优雅地解决过吗? 我是否遗漏了什么? 非常感谢您的想法和意见。
编辑: 为了消除一些疑惑,我想添加一些更多的细节。现在的问题不是 怎么做在 db 中存储 UTC 时间,而是从 UTC-> Local 和 Local-> UTC 的过程。正如@Max Zerbini 所指出的,显然将 UTC-> Local 代码放在视图中是明智的,但是使用 DateTimeExtensions
真的是答案吗?当从用户获取输入时,是否有必要接受日期作为用户的本地时间(因为 JS 将使用这个时间) ,然后使用 ModelBinder
转换为 UTC?用户的时区存储在数据库中,很容易检索到。