【问题标题】:Timezone Strategy时区策略
【发布时间】:2012-02-06 12:42:33
【问题描述】:

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

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

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

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

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

现在,在我渲染日期的每个视图上,我都需要调用一个方法以从 UTC 在本地时区渲染它。每次我向服务器发送提交日期时,我都需要将其从本地时区转换为 UTC。如果我忘记执行此操作,将会出现问题...提交的日期会出错,或者客户端报告和过滤器会出错。

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

很喜欢

[DateRange]
Public DateTime MyDate

我可以有类似的东西

[ConvertToUTC(offset)]
Public DateTime MyDate

无论如何,我想我唯一的方法是编写自定义数据注释以在时区中呈现它,并覆盖 MVC 3 模型绑定器,以便转换传入日期,除非我想包装任何日期在方法调用中。因此,除非有人有进一步的 cmets 或建议,否则它将是这两个选项之一,我只是很惊讶不存在这样做的东西。

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

编辑 2 我正在寻找类似 This http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx for MVC 3 视图和视图模型的东西。

最终编辑 我将 Epignosisx 的答案标记为正确,但还有一些 cmets 需要添加。 我在这里发现了类似的东西: http://dalldorf.com/blog/2011/06/mvc3-timezones-1/ 通过将时区放在第 2 部分中想要的人的 cookie 中,从客户端获取时区的实现(下面的链接,因为文章第一部分到第 2 部分的链接不起作用) http://dalldorf.com/blog/2011/09/mvc3-timezones-2/

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

【问题讨论】:

  • 我目前在 C# 和 SQL Server 中都使用 DateTimeOffset。思考同样的问题,但不知道我会在哪里结束。您可能会在 Daylight saving time and Timezone best practicesThe Death of DateTime? 找到一些有用的信息。
  • JavaScript 可以做到...您通过Date.UTC(...) 创建一个日期对象,然后调用.getTimezoneOffset() 来计算当地时间...
  • @vidas 但是我仍然在手动转换每个日期时间
  • 考虑使用一些会试图阻止您使用幼稚日期时间的东西。 (即,没有时区的日期时间) - Python 的日期时间在这方面非常出色,但也许 Nodatime 会有所帮助。
  • 我总是以 UTC 格式保存,但使用包含其时区信息的结构(夏令时也需要)。由于我知道用户时区,我可以将其转换为预期的 UTC,并使用自 1970 年以来的秒数转换为 JavaScript 日期。我的结构基于此:stackoverflow.com/questions/246498/…

标签: c# javascript asp.net-mvc-3 timezone utc


【解决方案1】:

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

从您的视图中,您将使用 @Html.DisplayFor(n => n.MyDateTimeProperty)

第二个问题更难解决。要将用户本地时间转换为 UTC,您可以覆盖 DefaultModelBinder。特别是 SetProperty 方法。这是一个简单的实现,它证明了这一点。它仅适用于 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);
        }
    }
}

【讨论】:

    【解决方案2】:

    首先,这主要是 How can I determine a web user's time zone? 的重复,我同意该回复的多数票:

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

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

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

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

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

    您不应依赖勤奋来进行正确的日期+时间格式和解析。 .NET 框架应为您处理此问题,初学者请参阅“How to: Set the Culture and UI Culture for ASP.NET Web Page Globalization”。

    结束语

    坦率地说,这一切都让人头疼。几年前我们放弃了实现,开始以 UTC 格式传输所有日期+时间信息,然后我们使用 Javascript 转换为本地时间并显示格式。恕我直言,这确实是唯一工作模型。

    【讨论】:

    • 我可以设置时区...在我的问题中没有任何地方要求我必须以编程方式确定客户端时区,尽管这肯定是一个不错的奖励。在格式化日期时间方面,我当然可以使用 uiculture,但我没有看到以相同方式设置时区信息的方法。也许您可以提供一个链接或示例,说明如何根据时区自动转换日期显示,并详细说明您在结束语中提到的仅 javascript 策略?
    【解决方案3】:

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

    【讨论】:

    • 我遇到了与 Sime Vidas 的解决方案相同的问题...无法确保数据的使用者(视图)始终像存在时那样被格式化是一个服务器端注释...它依赖于我非常小心地在服务器和视图上将格式转换为 UTC。
    【解决方案4】:

    这是不可能自动完成的,您必须做一些手动工作。

    1 如果您不想将用户的时区存储在数据库中

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

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

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

    【讨论】:

    • 这是模块的链接(通过 cprieto); link和github链接;link
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-14
    • 2012-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-03
    • 1970-01-01
    相关资源
    最近更新 更多