我的问题是双重的。
1)我正在编写一个论坛,我无法确定如何为论坛用户存储时区。他们将能够设置他们的时区,并相应地修改论坛上的所有日期。我是否必须创建一个带有时区名称和数字的数据库表来调整服务器时间? .NET是否在某处内置了时区支持?
2)一旦我弄清楚如何存储用户的时区,然后将DateTime对象修改到正确的时间,我就需要一种简单的方法将这个修改后的日期传递给MVC中的视图。例如,我有以下代码:
List<Topic> topics = board.Topics.OrderByDescending(x => x.Replies.Any()
? x.Replies.OrderBy(y => y.PostedDate).Last().PostedDate
: x.PostedDate).ToList();
此topics
对象作为视图模型对象的一部分传递给视图。视图循环遍历Model.Topics
并显示主题列表。问题是我不想在视图中进行时区修改,因为我认为这对视图负有太大的责任。有没有办法在LINQ查询中修改主题日期?
提前致谢!
答案 0 :(得分:7)
您可以获得时区列表System.TimeZoneInfo
。
var timeZones = System.TimeZoneInfo.GetSystemTimeZones();
foreach ( var timeZone in timeZones )
{
Console.WriteLine( "{0} - {1}", timeZone.Id, timeZone.DisplayName );
}
您可以使用该列表填充用户个人资料页面上的下拉列表。所选值应与每个用户的配置文件数据一起存储。
然后,您可以使用TimeZoneInfo.ConvertTime将任何日期时间转换为用户时区。假设你知道它是在哪个时区创建的。
var now = DateTime.Now;
Console.WriteLine( now );
Console.WriteLine( System.TimeZoneInfo.ConvertTime( now, TimeZoneInfo.Local, TimeZoneInfo.FindSystemTimeZoneById( "China Standard Time" ) ) );
至于何处进行此转换,您可以在控制器中执行此操作,而不是视图。您最好的选择是在主题的顶部创建一个视图模型,您可以在其中进行转换。
其他明智地创建一个帮助函数来执行转换,可以从您的视图中访问并适当地使用它。就个人而言,我不会害怕在视图中这样做。
如果厌倦了尝试在数据库中进行转换,则会严重限制对从数据库返回的数据执行对象缓存的能力。
此外,在将所有日期插入数据库之前,请考虑将其转换为UTC时间。这将使排序正确(关于夏令时),并且还限制托管环境移动时区或跨时区托管时可能出现的任何问题。
答案 1 :(得分:0)
我知道这是一个已回答的问题。我还加上我的几美分以供将来参考。这也是另一种方法。
我的完整解决方案如下。始终以UTC的形式存储在数据库中。您可以选择其他时区作为默认值。但随后计算变得复杂。如果你决定将你的主人搬到另一个国家,那就是问题。
首先,需要在一些保存用户信息的表中存储用户选择的时区。基本上我们将存储TimeZoneInfo.Id(String value)。这很容易再次创建TimeZoneInfo类。
接下来,创建用户定义的函数并将return设置为datetime。这将在需要服务器时间的整个DB中使用。代码如图所示,
Create FUNCTION [dbo].[fnGetDateTime] ()
RETURNS datetime
AS
BEGIN
RETURN GETUTCDATE()
END
这将返回UTC时间。我们可以在db中随处使用GETUTCDATE()方法。但是使用UDF可以灵活地进行维护。
我们可以在Date-time Class中使用方法扩展性。由于此解决方案基于asp.net,因此计算时间非常棘手。问题是,涉及3方。数据库服务器,Web服务器和用户。每个人都可以在不同的时区。但我们只需要在用户选择的时区和UTC时间中继。
我已经使用2个附加方法执行了DateTime Strucute。
Namespace Extensions
Public Module ModDateTimeExtensions
<System.Runtime.CompilerServices.Extension()> _
Public Function GetUserTimeFromUTC(ByVal dtUtcTime As DateTime, ByVal id As String) As DateTime
Return TimeZoneInfo.ConvertTimeFromUtc(dtUtcTime, TimeZoneInfo.FindSystemTimeZoneById(id))
End Function
<System.Runtime.CompilerServices.Extension()> _
Public Function SetUserTimeToUTC(ByVal dtUserTime As DateTime, ByVal id As String) As DateTime
Return TimeZoneInfo.ConvertTime(dtUserTime, TimeZoneInfo.FindSystemTimeZoneById(id), TimeZoneInfo.Utc)
End Function
End Module
End Namespace
重要的是你不应该在网络服务器时区进行计算。
然后基本上你可以进行如下转换。假设用户时区设置为“太平洋标准时间”。这需要在用户登录期间从DB中提取。
Dim dt as DateTime = FunctionToGetUTCTimeFromDB()
dt = dt.GetUserTimeFromUTC("Pacific Standard Time")
如果您想将用户时间保存为UTC,请致电
Dim dt as DateTime = GetUserSelectedTimeFromUI()
dt = dt.SetUserTimeToUTC("Pacific Standard Time")
这给予了以下灵活性,
如果需要在现有系统中实施,则编码更少,更少更改。
易于维护。
将来如果要实现用户可选择的日期时间格式,可以采用相同的方式进行小的更改。