Thursday, May 24, 2012

How to format a JSON date?


I'm taking my first crack at Ajax with jQuery. I'm getting my data onto my page, but I'm having some trouble with the JSON data that is returned for Date data types. Basically, I'm getting a string back that looks like this:




/Date(1224043200000)/



From someone totally new to JSON - How do I format this to a short date format? Should this be handled somewhere in the jQuery code? I've tried the jQuery.UI.datepicker plugin using $.datepicker.formatDate() without any success.



FYI: Here's the solution I came up with using a combination of the answers here:




function getMismatch(id) {
$.getJSON("Main.aspx?Callback=GetMismatch",
{ MismatchId: id },
function(result) {
$("#AuthMerchId").text(result.AuthorizationMerchantId);
$("#SttlMerchId").text(result.SettlementMerchantId);
$("#CreateDate").text(formatJSONDate(Date(result.AppendDts)));
$("#ExpireDate").text(formatJSONDate(Date(result.ExpiresDts)));
$("#LastUpdate").text(formatJSONDate(Date(result.LastUpdateDts)));
$("#LastUpdatedBy").text(result.LastUpdateNt);
$("#ProcessIn").text(result.ProcessIn);
}
);
return false;
}

function formatJSONDate(jsonDate){
var newDate = dateFormat(jsonDate, "mm/dd/yyyy");
return newDate;

}



This solution got my object from the callback method and displayed the dates on the page properly using the date format library.


Source: Tips4all

23 comments:

  1. Eval is not necessary. This will work fine:

    var date = new Date(parseInt(jsonDate.substr(6)));


    The substr function takes out the "\/Date(" part, and the parseInt function gets the integer and ignores the ")\/" at the end. The resulting number is passed into the Date constructor.

    ReplyDelete
  2. You can use this to get a date from json:

    var date = eval(jsonDate.replace(/\/Date\((\d+)\)\//gi, "new Date($1)"));


    and then you can use JavaScript Date Format script (1.2 KB when minified and gzipped) to display it as you want.

    ReplyDelete
  3. The original example:

    /Date(1224043200000)/


    does not reflect the formatting used by WCF when sending dates via WCF REST using the built-in JSON serialization. (at least on .NET 3.5, SP1)

    I found the answer here helpful, but a slight edit to the regex is required, as it appears that the timezone GMT offset is being appended onto the number returned (since 1970) in WCF JSON.

    In a WCF service I have:

    [OperationContract]
    [WebInvoke(
    RequestFormat = WebMessageFormat.Json,
    ResponseFormat = WebMessageFormat.Json,
    BodyStyle = WebMessageBodyStyle.WrappedRequest
    )]
    ApptVisitLinkInfo GetCurrentLinkInfo( int appointmentsId );


    ApptVisitLinkInfo is defined simply:

    public class ApptVisitLinkInfo {
    string Field1 { get; set; }
    DateTime Field2 { get; set; }
    ...
    }


    When "Field2" is returned as Json from the service the value is:

    /Date(1224043200000-0600)/


    Notice the timezone offset included as part of the value.

    The modified regex:

    /\/Date\((.*?)\)\//gi


    It's slightly more eager and grabs everything between the parens, not just the first number. The resulting time sinze 1970, plus timezone offset can all be fed into the eval to get a date object.

    The resulting line of JavaScript for the replace is:

    replace(/\/Date\((.*?)\)\//gi, "new Date($1)");

    ReplyDelete
  4. If you say in JavaScript,

    var thedate = Date(1224043200000);
    alert(thedate);


    you will see that it's the correct date, and you can use that anywhere in JavaScript code with any framework.

    ReplyDelete
  5. I ended up adding the " characters into Panos's regex to get rid of the ones generated by microsoft serializer for when writing objects into inline script:

    So if you have a property in your C# code behind that's something like

    protected string JsonObject { get { return jsSerialiser.Serialize(_myObject); }}


    and in your aspx you have

    <script type="text/javascript">
    var myObject = '<%= JsonObject %>';
    </script>


    you'd get something like

    var myObject = '{"StartDate":"\/Date(1255131630400)\/"}';


    Notice the double quotes.

    To get this into a form that eval will correctly deserialize I used:

    myObject = myObject.replace(/"\/Date\((\d+)\)\/"/g, 'new Date($1)');


    I use Prototype and to use it I added

    String.prototype.evalJSONWithDates = function() {
    var jsonWithDates = this.replace(/"\/Date\((\d+)\)\/"/g, 'new Date($1)');
    return jsonWithDates.evalJSON(true);
    }

    ReplyDelete
  6. Don't over-think this. Like we've done for decades, pass a numeric offset from the de-facto standard epoch of 1 Jan 70 Midnight GMT/UTC/&c in # of seconds (or milliseconds) since this epoch. JavaScript likes it, Java likes it, C likes it, the Internet likes it.

    ReplyDelete
  7. For those using Newtonsoft Json.NET, read up on how to do it via Native JSON in IE8, Firefox 3.5 plus Json.NET.

    For those that are too lazy, here are the quick steps. As JSON has a loose DateTime implementation, you need to use the IsoDateTimeConverter(),

    string jsonText = JsonConvert.SerializeObject(p, new IsoDateTimeConverter());


    The JSON will come through as

    "fieldName": "2009-04-12T20:44:55"


    Finally, some JavaScript to convert the ISO date to a JavaScript date:

    function isoDateReviver(value) {
    if (typeof value === 'string') {
    var a = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)(?:([\+-])(\d{2})\:(\d{2}))?Z?$/.exec(value);
    if (a) {
    var utcMilliseconds = Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], +a[5], +a[6]);
    return new Date(utcMilliseconds);
    }
    }
    return value;
    }


    I used it like this

    $("<span />").text(isoDateReviver(item.fieldName).toLocaleString()).appendTo("#" + divName);

    ReplyDelete
  8. Don't repeat yourself - automate date conversion using $.parseJSON()

    Answers to your post provide manual date conversion to Javascript dates. I've extended jQuery's $.parseJSON() just a little bit so it's able to automatically parse dates when you instruct it to. It processes Asp.net formatted dates (/Date(12348721342)/) as well as ISO formatted dates (2010-01-01T12.34.56.789Z) that are supported by native JSON functions in browsers (and libraries like json2.js).

    Anyway. If you don't want to repeat your date conversion code over and over again I suggest you read this blog post and get the code that will make your life a little easier.

    ReplyDelete
  9. There is no built in date type in JSON. This looks like the number of seconds / milliseconds from some epoch. If you know the epoch you can create the date by adding on the right amount of time.

    ReplyDelete
  10. In jQuery 1.5, as long as you have json2.js to cover for older browsers, you can deserialize all dates coming from Ajax as follows:

    (function () {
    var DATE_START = "/Date(";
    var DATE_START_LENGTH = DATE_START.length;

    function isDateString(x) {
    return typeof x === "string" && x.startsWith(DATE_START);
    }

    function deserializeDateString(dateString) {
    var dateOffsetByLocalTime = new Date(parseInt(dateString.substr(DATE_START_LENGTH)));
    var utcDate = new Date(dateOffsetByLocalTime.getTime() - dateOffsetByLocalTime.getTimezoneOffset() * 60 * 1000);
    return utcDate;
    }

    function convertJSONDates(key, value) {
    if (isDateString(value)) {
    return deserializeDateString(value);
    }
    return value;
    }

    window.jQuery.ajaxSetup({
    converters: {
    "text json": function(data) {
    return window.JSON.parse(data, convertJSONDates);
    }
    }
    });
    }());


    I included logic that assumes you send all dates from the server as UTC (which you should); the consumer then gets a JavaScript Date object that has the proper ticks value to reflect this. That is, calling getUTCHours() etc. on the date will return the same value as it did on the server, and calling getHours() will return the value in the user's local timezone as determined by their browser.

    This does not take into account WCF format with timezone offsets, though that would be relatively easy to add.

    ReplyDelete
  11. Posting in awesome thread:

    var d = new Date(parseInt('/Date(1224043200000)/'.slice(6, -2)));
    alert('' + (1 + d.getMonth()) + '/' + d.getDate() + '/' + d.getFullYear().toString().slice(-2));

    ReplyDelete
  12. Every one of these answers has one thing in common: they all store dates as a single value ( usually a string ).

    Another option is to take advantage of the inherent structure of JSON, and represent a date as list of numbers:

    { "name":"Nick",
    "birthdate":[1968,6,9] }


    Of course, you would have to make sure both ends of the conversation agree on the format (year,month,day), and which fields are meant to be dates,... but it has the advantage of completely avoiding the issue of date-to-string conversion. It's all numbers -- no strings at all. Also, using the order: year,month,day also allows proper sorting by date.

    Just thinking outside the box here -- a JSON date doesn't have to be stored as a string.

    ReplyDelete
  13. var newDate = dateFormat(jsonDate, "mm/dd/yyyy");


    are there any other option without using JQuery Libraries...?

    ReplyDelete
  14. Check up the Date ISO standard; kind of like this;
    "yyyy.MM.ddThh:mm"

    becomes; 2008.11.20T22:18

    ReplyDelete
  15. I get the date like this:

    "/Date(1276290000000+0300)/"


    In some examples the date is in slightly different formats:

    "/Date(12762900000000300)/"
    "Date(1276290000000-0300)"


    etc.

    So I came up with the following RegExp:

    /\/+Date\(([\d+]+)\)\/+/


    and the final code is:

    var myDate = new Date(parseInt(jsonWcfDate.replace(/\/+Date\(([\d+-]+)\)\/+/, '$1')));


    Hope it helps.

    Update:
    I found this link from Microsoft:
    How do I Serialize Dates with JSON?

    This seems like the one we are all looking for.

    ReplyDelete
  16. A late post, but for those who searched this post.

    Imagine this:

    [Authorize(Roles = "Administrator")]
    [Authorize(Roles = "Director")]
    [Authorize(Roles = "Human Resources")]
    [HttpGet]
    public ActionResult GetUserData(string UserIdGuidKey)
    {
    if (UserIdGuidKey!= null)
    {
    var guidUserId = new Guid(UserIdGuidKey);
    var memuser = Membership.GetUser(guidUserId);
    var profileuser = Profile.GetUserProfile(memuser.UserName);
    var list = new {
    UserName = memuser.UserName,
    Email = memuser.Email ,
    IsApproved = memuser.IsApproved.ToString() ,
    IsLockedOut = memuser.IsLockedOut.ToString() ,
    LastLockoutDate = memuser.LastLockoutDate.ToString() ,
    CreationDate = memuser.CreationDate.ToString() ,
    LastLoginDate = memuser.LastLoginDate.ToString() ,
    LastActivityDate = memuser.LastActivityDate.ToString() ,
    LastPasswordChangedDate = memuser.LastPasswordChangedDate.ToString() ,
    IsOnline = memuser.IsOnline.ToString() ,
    FirstName = profileuser.FirstName ,
    LastName = profileuser.LastName ,
    NickName = profileuser.NickName ,
    BirthDate = profileuser.BirthDate.ToString() ,
    };
    return Json(list, JsonRequestBehavior.AllowGet);
    }
    return Redirect("Index");
    }


    As you can see, I'm utilizing C# 3.0's feature for creating the "Auto" Generics. It's a bit lazy, but I like it and it works.
    Just a note: Profile is a custom class I've created for my web application project.

    ReplyDelete
  17. Check this for a generic solution for parsing date values in JSON strings:

    http://www.blog.activa.be/2010/03/12/HandlingDatesInJSONResponsesWithJQuery14TheEasyWay.aspx

    (assumes you're using jQuery 1.4 or higher)

    ReplyDelete
  18. FYI, for anyone using Python on the server side: datetime.datetime().ctime() returns a string that is natively parsable by "new Date()". That is, if you create a new datetime.datetime instance (such as with datetime.datetime.now), the string can be included in the JSON string, and then that string can be passed as the first argument to the Date constructor. I haven't yet found any exceptions, but I haven't tested it too rigorously, either.

    ReplyDelete
  19. Mootools solution:

    new Date(Date(result.AppendDts)).format('%x')


    Requires mootools-more. Tested using mootools-1.2.3.1-more on Firefox 3.6.3 and IE 7.0.5730.13

    ReplyDelete
  20. This is frustrating. My solution was to parse out the "\/ and \/" from the value generated by asp.net's JavaScriptSerializer so that, though JSON may not have a date literal, it still gets interpreted by the browser as a date, which is what all I really want:{"myDate":Date(123456789)}

    http://stackoverflow.com/questions/1341719/custom-javascriptconverter-for-datetime/3930187#3930187

    ReplyDelete
  21. var obj = eval('(' + "{Date: \/Date(1278903921551)\/}".replace(/\/Date\((\d+)\)\//gi, "new Date($1)") + ')');
    var dateValue = obj["Date"];

    ReplyDelete
  22. $.datepicker.formatDate('MM d,yy',new Date(parseInt(place the date that you get from the database here)));

    output : August 30,2011
    this doesnt give you the current time and date.. it displays whatever is there in your database.

    ReplyDelete
  23. Your JSON should probably be returning an object of some sort (well, a string representation thereof).

    "{ myDate : Date(1224043200000) }"


    Using jQuery, you can access your data object this way:

    $.get(
    "myJSONFile.php",
    function (data) {
    // data.myDate will be a date object.

    // to show in a short date format (eg: dd/mm/yyyy)
    alert (
    data.myDate.getDate() + "/"
    + (data.myDate.getMonth() + 1) + "/"
    + data.myDate.getFullYear()
    ); // alerts: "15/10/2008"
    }
    );

    ReplyDelete