MVC,JsonResult,DateTime and TimeZone

The jsonresult of date time is serializing to the string /Date and some integer value starting with 1970 . The problem is that the browser interprets this value accordingly to the LOCAL TimeZone – and thus the same date is going to be interpreted with a difference.

I was thinking that I can adjust from UTC time offset of the server( obtained with .NET from TimeZoneInfo.Local.BaseUtcOffset.TotalMinutes) and the UTC time offset of the client( obtained with (new Date()).getTimezoneOffset() + UTCServerMinutes; ). Unfortunately,the code does not work for SAMOA ( 13 hours difference).

Pay attention that the server is sending SAME data – just the browser is interpreting from the local user time zone.

So the solution is to convert the  date to a string ( I have chosed yyyy-MM-ddTHH:mm:ss) and interpret in javascript( see date2 below).

The server code – I have put my birthdate 16 april 1970

DateTime res = new DateTime(1970,04,16,22,0,0);
[HttpPost]
        public JsonResult GetDateBirth()
        {

            var str = res.ToString("s");
            return Json(new { date =res,datestring=str,ok = true });

        }

The Javascript code:

function GetJsonDate() {
        $.ajax({
            type: "POST",
            url: '@Url.Action("GetDateBirth")',
            datatype: "JSON",
            contentType: "application/json; charset=utf-8",
            success: function (returndata) {
                if (returndata.ok) {
                    window.alert('The server is sending:' + returndata.date + " -- " + returndata.datestring);
                    var d = parseInt(returndata.date.substr(6));
                    var date1 = new Date(d);
                    var date2 = dateFromSortable(returndata.datestring);
                    var date3= getDateString(returndata.date);
                    window.alert('original: ' + date1  + '\r\n'  + ' iso correct:'+ date2 + '\r\n'+ ' utc difference not good:' + date3);

                }
                else {
                    //this is an error from the server
                    window.alert(' error : ' + returndata.message);
                }

            }
        }
        );
    }
    function dateFromSortable(dateStr) {
        var parts = dateStr.match(/\d+/g);
        return new Date(parts[0],parts[1] - 1,parts[2],parts[3],parts[4],parts[5]);
    }
    
    function getDateString(jsonDate) {
        //does not work correctly for SAMOA - it have some hours difference
        var UTCServerMinutes = @serverMinutes;
        if (jsonDate == undefined) {
            return "";
        }
        var utcTime = parseInt(jsonDate.substr(6));

        var dateUtc = new Date(utcTime);

        var minutesOffset = (new Date()).getTimezoneOffset() + UTCServerMinutes;

        var milliseconds = minutesOffset * 60000;
        var d = new Date(dateUtc.getTime() + milliseconds)
        return d;
    }

How to test it:

Run the project. Click “Get Json Date” – and you will see the three dates equal.

image

Now change the time zone to Samoa ( or other,if you live in Samoa Winking smile)

image

Click again on “Get Json Date”  – the date will  same 16 april 1970 just for the date2  – obtained from dateFromSortable javascript function.

image

Please note that the local time zone is NOT affecting the values transmitted via ViewBag/ViewData/Model,but just the ones transmitted via Json.

The project can be downloaded from here


Posted

in

, ,

by

Tags:

Comments

18 responses to “MVC,JsonResult,DateTime and TimeZone”

  1. Tudor Avatar
    Tudor

    Si-au dat si la Microsoft seama de problemele astea, si in ASP.NET WebAPI au trecut la ISO8601 format pentru date in JSON, care nu mai variaza in functie de timezone: http://www.hanselman.com/blog/OnTheNightmareThatIsJSONDatesPlusJSONNETAndASPNETWebAPI.aspx

    1. Andrei Ignat Avatar
      Andrei Ignat

      Yes, but it dows not still work in plain old MVC ( even4) with JsonResult.

  2. Nicolas Boisvert Avatar
    Nicolas Boisvert

    We get rid of this by creating a custom JsonResult where the date formating is taken in charge by Newtonsoft.Json to wich ew create a csuton DateTime conversion ! Way cleaner !

    1. Andrei Ignat Avatar
      Andrei Ignat

      Did you test throughfully Newtonsoft.Json package? I am sure that is good – but I do not want to introduce more unknown differences between MVC default Json serializer and Newtonsoft Json serializer

      1. Tudor Avatar
        Tudor

        As you probably know, Newtonsoft.Json has been choosen also by Microsoft as the default JSON serializer in WebAPI, and is the most used library for this today..

  3. francesco abbruzzese Avatar
    francesco abbruzzese

    If you set properly the DateTimeKind of each datetime both the Microsoft serializer and the json serializer works in the same way. They behave differently just when the DateTimeKind is set to Unspecified that is when we dont declare clearly if the DateTime is in local or universal time. In such ambigous situation one serializer assume local time and the other universal time so they behave differentky. Moreover the browser doesnt interpret the datetime in local time it interprets it in utc time…but shows up it in local time of the browser…and this create the xonfusion

    1. Andrei Ignat Avatar
      Andrei Ignat

      Hello Francesco
      Please show code.

  4. francesco abbruzzese Avatar
    francesco abbruzzese

    suppose you have a datetime x expressed in local time. Before serializing it with ANY serializer one must be sure the fact it expresses a local time is explicitely declared by setting x.Kind =DateTimeKind.Local. After that ALL serializer will do the same thing, that is, converting it il Utc time before serializing it. This means the client will receive an Utc time. However, when it is written in the javascript consolle it is shown in the browser local time with the indication of the local time zone. This is normally acceptable. In fact if the server and client are in the same timezone the user will see exactly the same time we had on the server. If the user is in a different timezone the time will be automatically shown converted in the user timezone. Thiw behaviour is normally acceptable, However, it is not acceptable when other dates are not sent in json format but rendered directly on the server side say in a textbox. In this case there is an incongruence because the two dates would show in different timezones. In this case the only way is to send also the json date as a string to the clkent as you suggested. In any case it is simply false that the Microsoft serialize doesnt work properly while the newsoft serialize works properly. The only difference between them is that each of them assume a different Kind when no Kind is explicitely declared

    1. Andrei Ignat Avatar
      Andrei Ignat

      Yes, I know about Newtonsoft serializer. Just do not want to add another framework to existing one.

      1. Francesco Abbruzzese Avatar
        Francesco Abbruzzese

        The point I was trying to point out is exactly that the Newtonsoft serializer adds NOTHING new respect to Microsoft serializer for what concern Timezone problems. It makes just different assumptions when the Kind is set to Unspecified, so it appears to have a different behavior but this “different behavior” just comes from the error of not setting the Kind of a DateTime before sending it to the client. When the developer set the kind of a DateTime the two serializer behave exactly in the same way.

  5. Pavel Nazarov Avatar

    I published on github https://github.com/xunter/dateup js util to auto convert date strings to the Date object. And also, it auto-integrates with jQuery.ajax. So, after ajax.post/get you will receive js object with Date fields.

    It converts string in ISO8601 format to the Date object.

    It is not a wide library but just my expirience and seems to work.

    1. Andrei Ignat Avatar
      Andrei Ignat

      Thank you

  6. kasaye Avatar

    real thankful free to get this page

  7. Javier Avatar
    Javier

    var d = parseInt(returndata.date.substr(6));

    A little hacky huh? Only because the default json serializer uses that awful formatting for dates ‘/Datexxxxxxxx/’.

    Scott Hanselman has a post on his block about json and dates and recommends to use the newtonsoft json serializer to convert dates to ISO format instead. Many will tell you to do the same, it is much cleaner and Microsoft includes the newtonsoft.json serializer as the default one on Web Api.

    I use it to replace the default Json.Encode output when I need the controller dumping json data on the view manually. It also handles circular references, which should be reason enough to use it instead already.

    1. Andrei Ignat Avatar
      Andrei Ignat

      Yes, I know that JSonSerializer is default in WebAPI.However, it did not include as default in MVC4. Must be some incompatibilities then, right?

      1. Tudor Avatar
        Tudor

        Obviously they will never switch to another JSON serializer in MVC4 (and future versions) because that would be a breaking change for existing applications, and they must preserve the backwards compatibility.
        On the other hand, the developer has the option to change the JSON serializer/parser or to use ASP.NET WebAPI for proper REST endpoints that return JSON.

  8. Ray Grant Avatar

    question :
    when displaying “time” say in a label – why not use “code behind” ex (this is in C#)
    =======
    protected void Page_Load(object sender, EventArgs e)
    {
    if (!Page.IsPostBack)
    {
    this.lblCurrentDate.Text = DateTime.Now.ToString(“d”);

    1. Andrei Ignat Avatar
      Andrei Ignat

      I said already: the problem is affecting Ajax requests – not usual code

Leave a Reply

Your email address will not be published. Required fields are marked *