James
James

Reputation: 1188

Converting from UTC Datetime to local datetime in View

So I have inadvertently come up against the reality that Azure works with UTC time. This is ok, except for the fact I found this out only when it was deployed! (When it is in debug mode it just uses my comps time, so this was overlooked)

So I need to be able to just display the datetime to the user as there time. I don't mind (and prefer) it is in UTC. However I have a lot of different places that dates pop up in my application, so I'm wondering what is the quick and dirty solution to get all the displays showing the local time. I was thinking about using an Editor template for datetime. Is this a good idea? What would I use to do the conversion?

Upvotes: 4

Views: 3580

Answers (2)

Derrick
Derrick

Reputation: 2552

Here are editor and display templates I came up with that allow the user to enter and have displayed the time in their own timezone, and have it converted to UTC for submission.

It requires the UIHint attribute to be set to the custom value "UTCTime" for each model UTC DateTime field as shown below, to select the correct display and editor templates. DateTimes in models without this annotation will not be effected:

    [UIHint("UTCTime")]
    [DataType(DataType.DateTime)]
    public DateTime LastSeen { get; set; }

/Views/Shared/EditorTemplatesUTCTime.cshtml:

@model DateTime?
@{
    var name = Html.GetFieldNameForModel(); // See the HTML extension at the end of this post

    var boxName = name + ".Value";
    var boxId = name + "_Value";
    var divId = name + "_UTC";
}
@Html.TextBoxFor(m => m.Value, new { type = "datetime", onBlur ="$('#" + name + "').val(UTCDateFuncs.ToUTCDate($('#" + boxId + "').val()));$('#" + divId + "').html('UTC:' + $('#" + name + "').val());$('#" + boxId + "').attr('title','UTC:' + $('#" + name + "').val());" })<span id="@divId"></span>
<script>
    new function () {
        var utcVal = $('#@(boxId)').val();
        $('#@(boxId)').val(UTCDateFuncs.FromUTCDate(utcVal));
        $('#@(boxId)').attr('title', 'converted from UTC ' + utcVal);
    }
</script>
@Html.HiddenFor(m=>m)

\Views\Shared\DisplayTemplates\UTCTime.cshtml

@model DateTime?
@if(Model.HasValue){<span class="UTCTime">@Model</span>}

Required javascript in the site template, or somewhere (Not in the Template though):

// UTC Date
$(function () {
    $('.UTCTime').each(function () {
        var oldtext = $(this).html();
        var result = UTCDateFuncs.FromUTCDate(oldtext);

        $(this).html(result);
        $(this).attr("title", "Converted from UTC " + oldtext);
    });
});

var UTCDateFuncs = {
    ToUTCDate: function (datetext) {
        try {

            var n = new Date(datetext);
            offsetms = n.getTimezoneOffset() * 60 * 1000;

            n = new Date(n.valueOf() + offsetms);

            result = n.toDateString() + " " + n.toLocaleTimeString();

        }
        catch (ex) {
            console.warn("Error converting time", ex);
        }
        return result;
    },

    FromUTCDate: function (datetext) {
        var result;
        try {

            var n = new Date(datetext);
            offsetms = n.getTimezoneOffset() * 60 * 1000;

            n = new Date(n.valueOf() - offsetms);

            result = n.toDateString() + " " + n.toLocaleTimeString();

        }
        catch (ex) {
            console.warn("Error converting time", ex);
        }
        return result;
    }
};

Also utilitzes this HTML Extension: \Controllers\Extensions\HtmlExtensions.cs

using System;
using System.Web.Mvc;

public static class HtmlExtensions
{

    public static string GetFieldNameForModel<TModel>(this HtmlHelper<TModel> htmlHelper)
    {
        var ti = htmlHelper.ViewData.TemplateInfo;
        var name = ti.HtmlFieldPrefix;
        return name;
    }

}

This is used solely on our administrative pages, so there is a not very user friendly span after the text box that shows the result of the conversion for the editor box.

Upvotes: 1

astaykov
astaykov

Reputation: 30903

Will this help you?

The issue is that you don't really know the user's time zone on the server. You could at best guess one's culture, but not a time zone. And culture "en-us" can have at least 4 time zones assuming the user is in the US.

Another approach would be to have user choose/select a preffered timezone when working with your site. You could then save this choise in a cookie, or profile. Having the user's timezone, you could convert between time zones in method similar to this:

var localDateTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, timeZone.TimeZoneInfo);

Where you use the static method ConvertTimeFromUtc of TimeZoneInfo type. And also you have an instance of TimeZoneInfo (in my case a property of my custom type) which keeps the user's TimeZoneInfo setting.

Reffering back to the jQuery solution - you could use that, calling this small function on document.ready(). Just you have to keep in mind to add desired css class to your time display fields.

But at the end, if you are targeting multi-time-zone visitors, you may want to ask them for preffered timezone to do the convertion on the backend, and explicitly display that times are in UTC for users who didn't chose a preffered TimeZone.

Upvotes: 0

Related Questions