【问题标题】:MVC - UTC date to LocalTimeMVC - UTC 日期到 LocalTime
【发布时间】:2018-12-29 00:43:31
【问题描述】:

我们有一个 MVC 项目,我需要显示转​​换为用户本地时间的 UTC 日期。在我的模型中,我传递了 UTC 日期,在视图中,我正在尝试执行以下操作:

<%: Html.DisplayFor(m=> m.SomeDate.ToLocalTime()) %>

这会引发异常。谁能指出我如何将UTC日期转换为本地日期时间以在客户端显示的正确方向。我们将日期存储为 UTC,并且在显示时间这些日期将需要转换为本地机器等效值。

【问题讨论】:

标签: asp.net-mvc date


【解决方案1】:
DateTime now = DateTime.UtcNow;
DateTime localNow = TimeZoneInfo.ConvertTimeFromUtc(now, TimeZoneInfo.Local);

【讨论】:

  • 这需要在服务器端完成,而我说的是客户端
  • @Amitesh,在您问题的示例中,您也尝试在服务器端转换日期。
  • 我正在尝试使用 m.SomeDate.ToLocalTime()) %> 在客户端将日期转换为本地日期。
  • 使用上面的代码,我看到了这个问题 转换无法完成,因为提供的 DateTime 没有正确设置 Kind 属性。例如,当 Kind 属性为 DateTimeKind.Local 时,源时区必须为 TimeZoneInfo.Local。 (参数'sourceTimeZone'
【解决方案2】:

您需要在服务器端存储用户时区,然后使用类似的东西(虽然它应该在控制器中完成,而不是在视图中完成):

@TimeZoneInfo.ConvertTimeFromUtc(Model.CreatedOn, TimeZoneInfo.FindSystemTimeZoneById("E. Australia Standard Time"))

【讨论】:

    【解决方案3】:

    您不能在服务器上执行 ToLocalTime(),因为服务器是 UTC。您需要:

    1. 让客户端以某种方式发送它的时区(这可能很棘手,因为默认情况下您不会通过 GET 请求获取它)
    2. 让服务器向下发送 UTC,客户端将其转换为本地时间。如果您使用 AJAX,这自然会发生,但仅使用 razor view 会很麻烦:

    这是我用来使 Razor 视图的第二种方法非常容易的技巧:

    服务器使用特殊类“.mytime”和自定义属性“utc”中指定的 utc 时间(来自服务器)呈现元素:

       <div class="mytime" utc ="@date.ToString("o")"></div>
       <span class="mytime" utc ="2018-12-28T02:36:13.6774675Z"></span>
    

    注意 .ToString("o") 是 UTC 时间的写法。

    然后有一个本地jQuery函数遍历所有带有“mytime”类的元素,读取属性中的UTC值,然后进行转换。

    $(function () {
        var key = $(".mytime").each(function (i, obj) {
            var element = $(this); // <div> or <span> element. 
            var utc = element.attr("utc"); // "2018-12-28T02:36:13.6774675Z"
            var d = new Date(utc);
            var l = d.toLocaleString(); // Runs client side, so will be client's local time!
            element.text(l);
        });
    });
    

    然后我创建了一个用于渲染的 MVC razor 助手:

    public static MvcHtmlString LocalDate(this HtmlHelper helper, DateTime date)
    {
        // Must use MvcHtmlString to avoid encoding.
        return new MvcHtmlString(String.Format("<span class=\"mytime\" utc =\"{0}\"></span>", date.ToString("o")));
    }
    

    所以现在我的视图只包括上面的 JQuery 和脚本,然后:

    Created at @Html.LocalDate(Model.CreatedDate)
    

    因为这是在 jQuery 的 $() onload 中调用的,所以它会在服务器一直发送下来之后运行。

    工作就像一个魅力!

    【讨论】:

    • 我必须将 var utc = element.attr("utc"); 更改为 var utc = element.attr("utc") + 'Z'; 才能完成这项工作。
    【解决方案4】:

    在 mvc 中,您可以通过操作过滤器解决此问题。 请使用以下步骤:
    1) 在会话中存储客户端时区偏移信息。
    2) 创建 DatetimeConverter 助手类。

    public class DateTimeConverter
    {
        public static DateTime? ToLocalDatetime(DateTime? serverDate, int offset)    
        {
            if (serverDate == null) return null;
            return serverDate.Value.AddMinutes(offset * -1);
        }
    
    }
    

    3).创建动作过滤器。

    public class LocalDateTimeConverter : ActionFilterAttribute
    {
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
           var model = filterContext.Controller.ViewData.Model;
            if (model != null && filterContext.HttpContext.Session["LocalTimeZoneOffset"] != null)
               ProcessDateTimeProperties(model, filterContext);
            base.OnActionExecuted(filterContext);
        }
    
        private void ProcessDateTimeProperties(object obj, ActionExecutedContext filterContext)
        {
            if (obj.GetType().IsGenericType)
            {
                foreach (var item in (IList)obj)
                {
                    ProcessDateTimeProperties(item, filterContext);
                }
            }
            else
            {
                TypeAccessor member;
                List<PropertyInfo> props = new List<PropertyInfo>();
                props.AddRange(obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty).ToList());
                member = TypeAccessor.Create(obj.GetType());
                foreach (PropertyInfo propertyInfo in props)
                {
                    if (propertyInfo.PropertyType == typeof(DateTime) || propertyInfo.PropertyType == typeof(DateTime?))
                    {
                        {
                            member[obj, propertyInfo.Name] = DateTimeConverter.ToLocalDatetime((DateTime?)propertyInfo.GetValue(obj), ((int)filterContext.HttpContext.Session["LocalTimeZoneOffset"]));
                        }
                    }
                    else if (propertyInfo.PropertyType.IsGenericType && propertyInfo.GetValue(obj) != null)
                    {
                        foreach (var item in (IList)propertyInfo.GetValue(obj))
                        {
                            ProcessDateTimeProperties(item, filterContext);
                        }
                    }
                }
            }
        }
    }
    

    4). 对包含模型数据的操作应用 LocalDateTimeConverter 过滤器以返回视图。

    完成所有这些步骤后,您可以在视图中看到包含转换为本地日期时间的日期时间信息的结果。

    【讨论】:

      【解决方案5】:

      感觉有点杂乱无章,但这在 MVC3 客户端中有效

      @DateTime.Parse(Html.DisplayFor(m=> m.SomeDate).ToString()).ToLocalTime().ToString()
      

      【讨论】:

      • 我喜欢。它很干净,就在视野中。如果您想为不同的视图设置格式,这很容易——做得很好。它只是看起来像一个杂物。
      【解决方案6】:

      所有好的答案。我是这样做的:

      @Html.DisplayFor(m=> m.SomeDate.ToLocalTime()
          .ToString(
              CultureInfo.CurrentUICulture.DateTimeFormat.ShortDatePattern 
              + " " 
              + CultureInfo.CurrentUICulture.DateTimeFormat.LongTimePattern))
      

      【讨论】:

      • 这是给我的。谢谢!
      【解决方案7】:

      使用此代码将UTC时间转换为本地时间

      <%: Html.DisplayFor(m=> m.SomeDate.ToLocalTime().ToString()) %>
      

      您可以在剃须刀中使用以下代码

      @Html.DisplayFor(m=> m.SomeDate.ToLocalTime().ToString())
      

      【讨论】:

      • 我认为这行不通。你会得到一个异常:System.InvalidOperationException: '模板只能用于字段访问、属性访问、单维数组索引或单参数自定义索引器表达式。'
      【解决方案8】:

      将 UTC 日期时间转换为 LocalDate 也可以使用 jquery 来完成。使用 jquery 执行此操作的主要好处是,如果您将网站托管在 azure 上。上面给出的一些方法不起作用。只剩下一个使用 jquery / javascript 的选项。因为如果您的网站托管在 azure 上,则 Datetime.Now 将返回 datetime.now.tolocaltime() 的 utc 时间。请在 jquery 下面找到一个将 UTC 时间转换为 localdatetime 的示例。

      var date = new Date('2/8/2018 3:57:48 PM UTC');
      date.toString() // "Thu Feb 08 2018 21:27:48 GMT+0530 (India Standard Time)"
      

      【讨论】:

        【解决方案9】:

        在一个 .NET Core 项目中,我终于成功使用了以下剃须刀代码:

        @Model.DateUpdated.ToLocalTime().ToString(
                          CultureInfo.CurrentUICulture.DateTimeFormat.ShortDatePattern 
                          + " " + 
                          CultureInfo.CurrentUICulture.DateTimeFormat.LongTimePattern)
        

        (灵感来自 Kelly R 的回答)

        【讨论】:

          猜你喜欢
          • 2017-04-09
          • 2015-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-02-25
          • 1970-01-01
          • 1970-01-01
          • 2012-10-29
          • 2018-09-27
          相关资源
          最近更新 更多