Dealing with localized dates with ASP.NET MVC, kendo DateTimePicker and javascript

This is going to be yet another post on dealing with UTC and localized (browser, client) using ASP.NET MVC, Razor and kendo. It is of course only needed if your web app is going to be reached from various time zones – if not you might not need that. There are many posts out there covering parts of this, sometimes even greater parts, but still I had to put that all together. One of the most useful links was this post: How To Convert JavaScript Local Date to UTC And UTC To Local Date.

Many people deal with this topic trying to solve it generally by somehow saving it into a cookie or into the session somehow. My intention with this post is NOT this. I would like to solve it for our project for all kendo date time pickers we have. A general solution can be derived from that.

The solution
Everything we save into a database is to be in UTC. We can only convert from UTC on the client side (in the browser). We convert back to UTC on the server-side, when saving the view model containing the time zone offset.

Steps towards the solution

  1. Creating a view model containing the date and an offset property as follows
    // The view model
    public class SomeViewModel
    {
        /// <summary>
        /// Gets or sets the timezone offset minutes.
        /// </summary>
        public decimal TimezoneOffsetMinutes { get; set; }
    
        /// <summary>
        /// Gets or sets the date.
        /// </summary>
        public DateTime SomeDate { get; set; }
    }
    
  2. Adding input fields to the view
    @Html.HiddenFor(m => m.TimezoneOffsetMinutes)
    @(Html.Kendo().DateTimePickerFor(x => x.SomeDate).HtmlAttributes(new { @class = "kendo-utc-date" })
    
  3. Specifying a method which will calculate back from the local time to UTC:
    /// <summary>
    /// Gets the UTC time.
    /// </summary>
    /// <param name="dateTime">The date time.</param>
    /// <param name="dateTimeOffsetMinutes">The date time offset minutes.</param>
    /// <returns>
    /// The UTC time.
    /// </returns>
    private DateTime GetUtcTime(DateTime dateTime, decimal dateTimeOffsetMinutes)
    {
        return DateTime.SpecifyKind(dateTime.AddMinutes((double) dateTimeOffsetMinutes), DateTimeKind.Utc);
    }
    
  4. A javascript which will run for all kendo date time pickers marked with the class kendo-utc-date.
    var localizeDateTimePickerContainingUtcDate = function (selector) {
        $(selector).each(function () {
            var dateTimePicker = $(this).data("kendoDateTimePicker");
            var utcDate = dateTimePicker.value();
            var date = new Date();
            date.setTime(utcDate.getTime() - (date.getTimezoneOffset() * 60000));
            dateTimePicker.value(date);
        });
    };
    
    $(document).ready(function () {
        localizeDateTimePickerContainingUtcDate('input.kendo-utc-date');
    });
    
Advertisements

About Tamas Nemeth

Husband and proud father of two daughters in Nürnberg. I'm working as a Senior Software Developer and an enthusiastic Clean-Coder. I spend most of my free time with my family (playing, hiking, etc...). I also play table-tennis and badminton sometimes...
This entry was posted in Technical Interest and tagged , , , , , , , . Bookmark the permalink.

6 Responses to Dealing with localized dates with ASP.NET MVC, kendo DateTimePicker and javascript

  1. Venketash (Pat) Ramadass says:

    Thanks for the great post, it helped with a problem we were encountering now. Unless I misunderstood though I just wanted to mention that the value of the hidden TimezoneOffsetMinutes field also needs to be set within the JavaScript so that it can be used on the server side within GetUtcTime etc.

  2. Christian Mielke says:

    What do you with the proerty “TimezoneOffsetMinutes “? Where is it set?

  3. Troy Niemeier says:

    Thank you, Tamas!
    I was able to achieve this in a slightly different fashion, using TimeZoneInfo.Local.GetUtcOffset(DateTime.UtcNow).

    In my Controller Action Method I would set a ViewBag with the appropriate offset value,
    var offsetHours = Convert.ToInt32(TimeZoneInfo.Local.GetUtcOffset(DateTime.UtcNow).ToString().Split(‘:’)[0]);
    // “-05:00:00” as a String
    // stored as -5
    ViewBag.offsetMilliseconds = offsetHours * 3600000;
    // 60 minutes * 60 seconds * 1000 milliseconds
    // -18000000

    Then in my View’s HTML markup,

    @(Html.Kendo().DateTimePicker()
    .Name(“transactionDateTime”)
    .Value(Model.TransactionDateTime)
    .Format(“MM/dd/yyyy hh:mm tt”)
    .Events(e => e.Change(“transactionDateTimeChange”))
    )

    From here, I can reference this hidden value and do the math in my Javascript function:

    var offset = parseInt($(“#ms_timezoneOffset”).val());
    var dateTimePicker = $(“#transactionDateTime”).data(“kendoDateTimePicker”);
    var utcDateTime = dateTimePicker.value();
    var date = new Date();
    date.setTime(utcDateTime.getTime() + offset);
    dateTimePicker.value(date);

    Thank you, again! It’s a terrible problem to need to fix ourselves. But, I really appreciate your insights!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s