Displaying date/time using the user timezone in ASP.NET MVC

This post will show you how you can display date/time using the user timezone (without it being configured anywhere in your application).

Storaging dates in your data source

The first thing you have to do is to make sure that all dates are stored using Universal Cordinated Time (UTC).

The easiest way to do that is to convert it like this:

var dbDate = myDate.ToUniversalTime();

When loading dates simply do no conversion at all.

Displaying the date/time

The date/time can not be formatted server-side since the HTTP request contains no information about the time zone. Instead we have to do it client side (or start using AJAX to configure server side).

Hence we need to push the date to the client in a way that would allow us to reformat it. The easiest way to do that is to create a display template. The great thing with that is that all date/times will automatically be reformatted if you are using Html.DisplayFor.

Create a template named /Views/Shared/DisplayTemplates/DateTime.cshtml with the following content:

@model DateTime
<span data-date="@Model.Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds">@Model.ToString()</span>

We simply display the date as UTC. But we do also include the unix date in an attribute. We’ll use that to do the formatting.

Formatting the date/time

Now we only have the formatting left. For that we’ll use a combination of standard javascript and jQuery.

Add this somewhere in your application:

<script type="text/javascript">
$(function(){
    $('[data-date]', container).each(function () {
        // the date construct will automatically convert to local time
        var localDate = new Date(parseInt($(this).attr('data-date')));

        //display time only for today, otherwise only the date.
        // feel free to use your own logic
        var now = new Date();
        if (localDate.getDate() == now.getDate() && localDate.getFullYear() == now.getFullYear() && now.getMonth() == localDate.getMonth()) {
            $(this).html(localDate.toLocaleTimeString());
        } else {
            $(this).html(localDate.toLocaleDateString());
        }
    });
});
</script>

End result

Done.


  • aterra103

    Nice thanks for the post

  • Tone Engel

    Thanks!

  • sherin

    good………

  • Ruud Lenders

    This works great. But for some reason, I had to remove “, container” first.R

    • Karate Dad

      Me too.

  • Ramakant Bhoi

    my database in US, datetime is of US and client is india or somewhere else, i want to select his/her data as per client local time(based on his timezone) then how should i write the query to get proper data of the client when he is in india ,and his data is in US. and datetime is in US datetime..using oracle and asp.net

  • kenlewisjr

    Brilliant, works great. I also had to remove “, container” first.

  • Warren Dodsworth

    Thanks, looks like a great solution to the Option 1 of how to deal with TimeZones.
    Could I ask
    1. How does the new Date() automatically convert the millisecond value to the users Local time?
    2. How does the server know what timezone the incoming time is from to convert it to Utc – var dbDate = ToUniversalTime();
    2.a. The server could be informed using jsTimeZoneDetect + NodaTime to convert the incoming User time (their timezone) to UTC
    3. How / if the solution deals with Daylight savings time?

    • Karate Dad

      This is actually designed so that the javascript function above is run against each field that is displayed. Since it is javascript running client side, it knows the users local time zone. So it should deal with daylight savings just fine. The magic is how MVC wraps this all up so nicely for us.

  • Karate Dad

    This works great, but what about Null date fields? I am getting the following server side error:

    “The model item passed into the dictionary is null, but this dictionary requires a non-null model item of type ‘System.DateTime’.”

    So, I ended up changing the DisplayTemplate to this:

    @model Nullable
    @{
    DateTime dt = DateTime.Now;
    if (Model == null)
    {

    }
    else
    {
    dt = (System.DateTime)Model;
    @Model.ToString()
    }

    }

  • Kenn Thompson

    Wonderful article. I used it, with the following caveats: In my data, there are times when I’ve simply stored a date (like birthday) and others where the time component is important (like events). I adjusted like so:

    DateTime.cshtml:
    @model Nullable
    @{
    if (!(Model == null) && !(Model == new DateTime(1970, 1, 1)))
    {
    if (Model.Value.Hour == 0 && Model.Value.Minute == 0 && Model.Value.Second == 0 && Model.Value.Millisecond == 0)
    {
    @Model.ToString()
    }
    else
    {
    @Model.ToString()
    }
    }
    }

    included common js:
    $(function(){
    $(‘[data-date]’).each(function () {
    // the date construct will automatically convert to local time
    var localDate = new Date(parseInt($(this).attr(‘data-date’)));
    $(this).html(localDate.toLocaleDateString());
    });
    $(‘[data-datetime]’).each(function () {
    // the date construct will automatically convert to local time
    var localDate = new Date(parseInt($(this).attr(‘data-datetime’)));
    $(this).html(localDate.toLocaleString());
    });
    });

  • Flavio

    what about the performance issues you have when using the attribute selector in jquery? Besides, you’d need to run the javascript for every partial page loading you do using ajax.

    • http://blog.gauffin.org/ jgauffin

      There is no perfect solution for a problem. You have to choose the solution that works best in your situation, and this one might not be it. If you’ve come to the conclusion that the attribute selector is too slow or that it’s too much work to load the script in your ajax partials: Try another solution. cheers.