C# 时区策略

C# 时区策略,c#,javascript,asp.net-mvc-3,timezone,utc,C#,Javascript,Asp.net Mvc 3,Timezone,Utc,我正在构建一个MVC 3应用程序,其中用户可能不在同一时区,因此我的目的是将所有内容存储在UTC中,并在视图中从UTC转换为本地时间,在提交时将localtime转换为UTC 做一些浏览,虽然似乎没有很多好的解决方案。老实说,我希望至少有一个属性可以自动将UTC时间转换为本地时间,但它似乎不存在 我觉得只要努力将每个输入手动转换为UTC,并将每个视图手动转换为本地时间显示,就很容易出错,并且在时间未转换为UTC或从UTC转换为UTC的情况下,很难检测到错误 有没有关于如何作为一项总体战略来处理这

我正在构建一个MVC 3应用程序,其中用户可能不在同一时区,因此我的目的是将所有内容存储在UTC中,并在视图中从UTC转换为本地时间,在提交时将localtime转换为UTC

做一些浏览,虽然似乎没有很多好的解决方案。老实说,我希望至少有一个属性可以自动将UTC时间转换为本地时间,但它似乎不存在

我觉得只要努力将每个输入手动转换为UTC,并将每个视图手动转换为本地时间显示,就很容易出错,并且在时间未转换为UTC或从UTC转换为UTC的情况下,很难检测到错误

有没有关于如何作为一项总体战略来处理这一问题的建议

编辑 每个人似乎都被“如何获取客户端时区”这一条所困扰,正如我在其中一条评论中提到的,这与我无关。我对确定他们时区的用户设置很满意,所以假设我已经知道客户端时区是什么…这并不能解决我的问题

现在,在渲染日期的每个视图上,我都需要调用一个方法从utc在本地时区渲染日期。每次我向服务器发送提交日期时,我都需要将其从本地时区转换为UTC。如果我忘记这样做,将会有问题…要么提交日期错误,要么客户端报告和过滤器错误

我所希望的是一种更自动化的方法,特别是因为视图模型在MVC 3中是强类型的,我希望sum magic能够至少在时区自动渲染,如果不处理提交,就像日期格式或范围可以由属性控制一样

很像

[DateRange]
Public DateTime MyDate
我可以吃点像这样的东西

[ConvertToUTC(offset)]
Public DateTime MyDate
无论如何,我想我唯一的方法就是编写一个自定义数据注释,在时区中呈现它,并在MVC 3模型绑定器上进行覆盖,以便转换传入日期,除非我想在方法调用中包装ever date。因此,除非有人有进一步的意见或建议,否则这将是这两种选择之一,我只是感到惊讶的是,还没有什么东西可以做到这一点

如果我真的实现了一个解决方案,我一定会发布它

编辑2 像这样的MVC3视图和视图模型是我所寻找的

最终编辑 我把epignosisx的答案标记为正确,但也有一些评论要补充。 我在这里发现了类似的东西: 实现了从客户端获取时区,方法是将时区放在cookie中,供第2部分中需要的人使用(下面的链接,因为本文第一部分到第2部分的链接不起作用)


重要的是要注意,使用这些方法,您必须使用Editfor和Displayfor,而不是像TextForFor这样的东西,因为只有Editfor和Displayfor使用元数据提供程序来告诉MVC如何在模型上显示该类型的属性。如果您直接在视图(@model.MyDate)中访问模型值,则不会发生转换。

您可以使用类似的方式显示日期/时间。有助于设置格式和当地时间。

首先,这主要是重复的,我同意大多数人对这一回答的投票:

我见过的最流行的(=标准?)确定时区的方法 “环顾四周”只是简单地询问用户自己。如果你的网站 需要订阅,这可以保存在用户的配置文件数据中。 对于anon用户,日期可以显示为UTC或GMT或其他格式 这样

也就是说,自动设置该值的最常用方法是使用javascript的Date()。然后可以通过cookie或ajax请求将其反馈给服务器,并与用户的配置文件、会话或cookie一起存储

最后,我仍然认为您应该允许用户更改此设置,以便您不仅可以确定UTC偏移,还可以确定实际时区和夏令时信息

当从用户收集输入时,通过DateTime与UTC之间的转换就足够了。当客户端是托管代码时,DateTimeOffset非常好;然而,对于纯html/javascript,它真的不会给你带来太多好处。此外,大多数应用程序不一定需要DateTimeOffset的附加信息,除非您打算向其他用户显示原始时区信息

我只想努力地手动转换每个 输入UTC并手动将每个视图转换为本地时间显示 将非常容易出错,并导致难以检测到的错误 时间不转换为或从

您不应该依赖diligence来获得正确的日期+时间格式和解析。NET framework应该为您处理此问题,初学者请参见“”

结束语


坦率地说,这是一件令人头痛的事。几年前我们放弃了这个实现,开始以UTC传输所有日期+时间信息,然后我们使用Javascript转换为本地时间和显示格式。这确实是IMHO的唯一工作模式。

这不是自动实现的,您必须进行一些手动操作

1如果不想在db中存储用户的时区

1.1不带母版页:正如csharptest.net建议的那样,使用java脚本的getDateTimeOffset()获取时区偏移量,在cookie中设置值,编写模块检查cookie(如果不存在cookie),插入java脚本代码并使用模块插入cookie

1.2使用母版页:相同,但无需编写模块进行检查

2以db为单位存储用户时区(最佳和最简单)
无需使用javascript获取时区,只需根据用户的时区转换datetime。

您可以通过使用网站范围的datetime显示模板来处理将UTC转换为用户本地时间的问题

从您的视图中,您可以使用@Html.DisplayF
public class MyDefaultModelBinder : DefaultModelBinder
{
    protected override void SetProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor, object value)
    {
        //special case for DateTime
        if(propertyDescriptor.PropertyType == typeof(DateTime))
        {
            if (propertyDescriptor.IsReadOnly)
            {
                return;
            }

            try
            {
                if(value != null)
                {
                    DateTime dt = (DateTime)value;
                    propertyDescriptor.SetValue(bindingContext.Model, dt.ToUniversalTime());
                }
            }
            catch (Exception ex)
            {
                string modelStateKey = CreateSubPropertyName(bindingContext.ModelName, propertyDescriptor.Name);
                bindingContext.ModelState.AddModelError(modelStateKey, ex);
            }
        }
        else
        {
            //handles all other types
            base.SetProperty(controllerContext, bindingContext, propertyDescriptor, value);
        }
    }
}