时区战略

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

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

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

关于如何将此作为一般战略处理的任何建议?

编辑每个人似乎都非常坚持“如何获得客户端时区”这篇文章,正如我在其中一条评论中提到的那样,并不是我关注的问题。 我很好用一个用户设置确定他们的时区,所以假设我已经知道客户端时区是什么…这不能解决我的问题。

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

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

所以喜欢

[DateRange] Public DateTime MyDate 

我可以有类似的东西

 [ConvertToUTC(offset)] Public DateTime MyDate 

无论如何,我想我的唯一方法就是编写自定义数据注释以在时区中呈现它,并在MVC 3模型绑定器上覆盖,以便转换传入日期,除非我想在方法中包装任何日期呼叫。 因此,除非有人有进一步的意见或建议,否则它将是这两个选项中的一个,我只是惊讶于已经不存在的事情。

如果我确实实施了解决方案,我一定会发布它。

编辑2像这样的http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx用于MVC 3视图和视图模型是我正在寻找的。

最终编辑我将epignosisx的答案标记为正确,但也有一些评论要添加。 我在这里找到了类似的东西: http : //dalldorf.com/blog/2011/06/mvc3-timezones-1/通过将时区放在cookie中为第2部分中需要的人提供时区的实现(链接如下,因为文章第一部分到第2部分的链接不起作用) http://dalldorf.com/blog/2011/09/mvc3-timezones-2/

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

您可以通过使用网站范围的DisplayTemplate for DateTime来处理将UTC转换为用户本地时间的问题。

从你的视图中你可以使用@ Html.DisplayFor(n => n.MyDateTimeProperty)

第二个问题更难解决。 要将用户本地时间转换为UTC,您可以覆盖DefaultModelBinder 。 特别是方法SetProperty 。 这是一个天真的实现,certificate了这一点。 它只适用于DateTime但可以很容易地扩展到DateTime? 。 然后将其设置为Global.asax中的默认绑定器

 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); } } } 

首先,这主要是我如何确定网络用户的时区? ,我同意大多数人对此回复的投票:

确定我所看到的时区的最流行的(==标准?)方式只是询问用户自己。 如果您的网站需要订阅,则可以将其保存在用户的个人资料数据中。 对于匿名用户,日期可以显示为UTC或GMT等。

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

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

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

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

您不应该依赖勤勉的正确日期+时间格式和解析。 .NET框架应该为您处理这个问题,对于初学者来说,请参阅“ 如何:为ASP.NET网页全球化设置文化和UI文化 ”。

结束语

坦率地说,这是颈部疼痛。 几年前我们抛弃了实现并开始以UTC格式传输所有日期+时间信息,然后我们使用Javascript转换为本地时间和显示格式。 这真是恕我直言的唯一工作模式。

您可以使用MomentJS之类的东西来显示日期/时间。 有助于格式化和当地时间。

这是不可能的,你必须做一些手工工作。

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

1.1没有母版页:正如csharptest.net建议使用java脚本的getDateTimeOffset()来获取时区偏移量,在cookie中设置值,编写一个模块来检查cookie是否存在cookie插入java脚本代码和cookie使用模块。

1.2使用masterpage:同样但不需要编写模块进行检查。

2将用户的时区存储在数据库中(最好和最简单)无需使用javascript来获取时区,只需根据用户的时区转换日期时间。