MVC - UTC date to LocalTime
We have a MVC project and I need to display a UTC date converted to users local time. In my model I 开发者_如何转开发am passing the UTC date and in the view I am trying to do the following:
<%: Html.DisplayFor(m=> m.SomeDate.ToLocalTime()) %>
This throws an exception. Can anybody point me in the correct direction on how to convert the UTC date to local datetime for display at customer end. We will be storing dates as UTC and at display time these dates will need to be converted to the local machine equivalent.
DateTime now = DateTime.UtcNow;
DateTime localNow = TimeZoneInfo.ConvertTimeFromUtc(now, TimeZoneInfo.Local);
You will need to store the users timezone server side and then use something like this (although it should be done in the controller, not the view):
@TimeZoneInfo.ConvertTimeFromUtc(Model.CreatedOn, TimeZoneInfo.FindSystemTimeZoneById("E. Australia Standard Time"))
You can't do ToLocalTime() on the server since the server is in UTC. You either need to:
- Have the client somehow send up it's timezone (this can be tricky since you won't get it by default with a GET request)
- Have the server send down UTC and the client converts it to the local time. This happens naturally if you're using AJAX, but is cumbersome with just a razor view:
Here's a trick I used for to make the 2nd approach very easy for Razor views:
The server renders elements with a special class ".mytime" and the utc time (from server) specified in a custom attribute "utc":
<div class="mytime" utc ="@date.ToString("o")"></div>
<span class="mytime" utc ="2018-12-28T02:36:13.6774675Z"></span>
Note that .ToString("o") is how to write in UTC time.
And then have a local jQuery function iterate through all the elements with "mytime" class, read the UTC value in the attribute, and then do the conversion.
$(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);
});
});
I then created a MVC razor helper for rendering:
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")));
}
So now my view just includes JQuery and script above and then does:
Created at @Html.LocalDate(Model.CreatedDate)
Since this is invoked in jQuery's $() onload, it runs after the server has sent down all the times.
Worked like a charm!
It feels like a bit of a kludge but this worked in an MVC3 client
@DateTime.Parse(Html.DisplayFor(m=> m.SomeDate).ToString()).ToLocalTime().ToString()
In mvc you can solve this issue by action filter.
Please use the following steps:
1) Store client timezone offset info in session.
2) Create DatetimeConverter helper class.
public class DateTimeConverter
{
public static DateTime? ToLocalDatetime(DateTime? serverDate, int offset)
{
if (serverDate == null) return null;
return serverDate.Value.AddMinutes(offset * -1);
}
}
3).Create action filter.
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).Apply LocalDateTimeConverter filter on action which contains model data to return view.
After these all step you can see the result in view which contains dateTime info converted into local dateTime.
All good answers. I did mine like this:
@Html.DisplayFor(m=> m.SomeDate.ToLocalTime()
.ToString(
CultureInfo.CurrentUICulture.DateTimeFormat.ShortDatePattern
+ " "
+ CultureInfo.CurrentUICulture.DateTimeFormat.LongTimePattern))
Use this code to convert utc time to local time
<%: Html.DisplayFor(m=> m.SomeDate.ToLocalTime().ToString()) %>
You can use use following code in razor
@Html.DisplayFor(m=> m.SomeDate.ToLocalTime().ToString())
Converting UTC Date Time To LocalDate Can be done using jquery as well. Main Benefit of doing it using jquery is in case you have hosted your website on azure. some methods given above will not work. Only one option will be left to be used that's using jquery / javascript. As Datetime.Now in case of your website is hosted on azure will return utc time for datetime.now.tolocaltime(). Please find below an example in jquery to convert UTC time to 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)"
In a .NET Core project, I finally had success with the following razor code:
@Model.DateUpdated.ToLocalTime().ToString(
CultureInfo.CurrentUICulture.DateTimeFormat.ShortDatePattern
+ " " +
CultureInfo.CurrentUICulture.DateTimeFormat.LongTimePattern)
(Inspiration taken from Kelly R's answer)
精彩评论