关于.net:根据存储的时区修改ASP.NET MVC C#中的日期

Modifying dates in ASP.NET MVC C# based on stored time zone

我的问题是双重的。

1)我正在编写一个论坛,我无法弄清楚如何为论坛用户存储时区。他们将能够设置他们的时区,并相应地修改论坛上的所有日期。我是否必须创建一个带有时区名称和数字的数据库表来调整服务器时间? .NET是否在某处内置了时区支持?

2)一旦我弄清楚如何存储用户的时区,然后将DateTime对象修改到正确的时间,我就需要一种简单的方法将这个修改后的日期传递给MVC中的视图。例如,我有以下代码:

1
2
3
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查询中修改主题日期?

提前致谢!


您可以获得时区列表System.TimeZoneInfo

1
2
3
4
5
6
var timeZones = System.TimeZoneInfo.GetSystemTimeZones();

foreach ( var timeZone in timeZones )
{
  Console.WriteLine("{0} - {1}", timeZone.Id,  timeZone.DisplayName );
}

您可以使用该列表填充用户配置文件页面上的下拉列表。所选值应与每个用户的配置文件数据一起存储。

然后,您可以使用TimeZoneInfo.ConvertTime将任何日期时间转换为用户时区。假设您知道它创建了哪个时区。

1
2
3
var now = DateTime.Now;
Console.WriteLine( now );
Console.WriteLine( System.TimeZoneInfo.ConvertTime( now, TimeZoneInfo.Local, TimeZoneInfo.FindSystemTimeZoneById("China Standard Time" ) ) );

至于在何处进行此转换,您可以在控制器而不是视图中执行此操作。您最好的选择是在主题的顶部创建一个视图模型,您可以在其中进行转换。

其他明智的方法是创建一个辅助函数来进行转换,可以从视图中访问并适当地使用它。就个人而言,我不会害怕在视图中这样做。

厌倦了尝试在数据库中进行转换,您将严重限制对从数据库返回的数据执行对象缓存的能力。

此外,在将所有日期插入数据库之前,请考虑将其转换为UTC时间。这将使排序正确(关于夏令时),并且还限制在托管环境被移动时区或跨时区托管时可能出现的任何问题。


我知道这是一个已回答的问题。我还加上我的几美分以供将来参考。这也是另一种方法。

我的完整解决方案如下。始终以UTC的形式存储在数据库中。您可以选择其他时区作为默认值。但随后计算变得复杂。如果你决定将你的主人搬到另一个国家,那就是问题。

数据库

首先,需要在一些保存用户信息的表中存储用户选择的时区。基本上我们将存储TimeZoneInfo.Id(String value)。这很容易再次创建TimeZoneInfo类。

接下来,创建用户定义的函数并将return设置为datetime。这将在需要服务器时间的整个DB中使用。代码如图所示,

1
2
3
4
5
6
7
8
9
10
11
12
Create FUNCTION [dbo].[fnGetDateTime] ()

RETURNS datetime

AS

BEGIN

RETURN GETUTCDATE()


END

这将返回UTC时间。我们可以在db中随处使用GETUTCDATE()方法。但是使用UDF可以灵活地进行维护。

我们可以在Date-time Class中使用方法可扩展性。由于此解决方案基于asp.net,因此计算时间非常棘手。问题是,涉及3方。数据库服务器,Web服务器和用户。每个人都可以在不同的时区。但我们只需要在用户选择的时区和UTC时间上进行中继。

我用2个addtional方法执行了DateTime Strucute。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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中提取。

1
2
3
Dim dt as DateTime = FunctionToGetUTCTimeFromDB()

dt = dt.GetUserTimeFromUTC("Pacific Standard Time")

如果您想将用户时间保存为UTC,请致电,

1
2
3
Dim dt as DateTime = GetUserSelectedTimeFromUI()

dt = dt.SetUserTimeToUTC("Pacific Standard Time")

这给予了以下灵活性,

如果需要在现有系统中实现,则编码更少,更少更改。

易于维护。

将来如果要实现用户可选日期时间格式,可以采用相同的方式进行小改动。