views:

26847

answers:

21

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 that is returned for Date data types. Basically, I'm getting a string back that looks like this:

/Date(1224043200000)/

From a total newbie at 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() wiuth no 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.

+2  A: 

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.

johnstok
+7  A: 

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 with any framework

John Boker
That's what I would have thought too except it ends up being: var thedate = /Date(1224043200000)/; at least for me...
rball
very nice trick !
steven spielberg
+33  A: 

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.

Panos
Thanks for the reference to the library. I was able to use this to get my short date format.
Mark Struzinski
I think there is something wrong in that line of JS. The last two slashes act as comments. I don't know regexp enough to fix it.
orandov
There's nothing wrong with the line, the sequence is \// . First slash is escaped so it does not count like a comment. It's your editor tricking you, the line will work fine.
legenden
-1 for the use of eval.
pst
@pst eval is needed. You don't know what you're talking about.
rball
@rball, nonsense: `jsonDate = new Date(+jsonDate.replace(/\/Date\((\d+)\)\//, '$1'));`
eyelidlessness
pst was correct, it is possible to do this in a variety of ways without 'eval'. Crockford says that 'eval Is Evil' because it is less readable and is less secure, furthermore he may further imply that it is less efficient and more dangerous because it hits the javascript compiler.
Mark Rogers
2pst: Instead of eval — (new Function('return ' + json))()
Edy Gomolyako
Based on what was suggested I made it this way: /** * Convert a Json datetime to Date object * @param {Object} jsonDateTime For example /Date(1224043200000)/ * @return {Date} return Date object */ Date.prototype.fromJson = function(jsonDateTime) { var date = new Date(parseInt(jsonDateTime.replace(/^\/Date\((\d+)\)\/$/gi, '$1'), 10)); return date; };
Gad D Lord
-1 for use of eval. It really isn't necessary.
Roy Tinker
@Edy: `new Function` is almost as bad as `eval`: http://dev.opera.com/articles/view/efficient-javascript/?page=2#avoideval
Marcel Korpel
@Gad: please don't post code in a comment; just formulate a new answer.
Marcel Korpel
+1  A: 

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"
    }
);
nickf
.NET returns it a different way.
rball
how does it return it?
nickf
/Date(1224043200000)/ not Date(1224043200000)
rball
that's strange. wouldn't that make it a regex?
nickf
No, it's inside quote marks.
Emtucifor
A: 

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

becomes; 2008.11.20T22:18

Thomas Hansen
+20  A: 

Here's a good explanation of why Microsoft chose this format to represent JSON dates in ASP.NET:

http://weblogs.asp.net/bleroy/archive/2008/01/18/dates-and-json.aspx

Chris Kentfield
A: 

Hi !

I attempted to "port" tips from here to convert the json format, the MS-WCF services return for dates, like:

"\/Date(1245108047000+0200)\/"

But nothing works. Any more ideas??

br--mabra

mabra
Try TimTheTinker's answer above. The +0200 is a time zone offset, and his answer works whether the offset is included or not.
Remi Despres-Smyth
Though I believe it wills trip off the timezone offset and the Javascript date instance will use yours instead.
Remi Despres-Smyth
A: 
var newDate = dateFormat(jsonDate, "mm/dd/yyyy"); 

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

Regards BK

blgnklc
+4  A: 

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);
}
Chris Woodward
A: 

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.

Ray Linder
so everytime you add a new role [Authorize(Roles = "Human Resources")] , you have to compile and deploy? wow.... :)
AlexanderN
+1  A: 

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.

Xepoch
+3  A: 

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)");
Aaron
Aaron, thanks for sharing. This worked like a charm.
Trent
It is what i search!!! Thank you
Kate
+2  A: 

For those using Newtonsoft JSON.Net, read up on how to do it via the link here

http://james.newtonking.com/archive/2009/04/12/native-json-in-ie8-firefox-3-5-plus-json-net.aspx

for those too lazy, here is 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 IsoDate to 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);
Jason Jong
+62  A: 

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.

Roy Tinker
This worked for me, thanks !
Jhonny D. Cano -Leftware-
+1 for not using eval, and for also working if a timezone offset is included in the string (which was the case for me).
Remi Despres-Smyth
Worked for me too..Thanks
Mahin
+1 I was going to post the following update to the original eval answer as follows: new Date(parseInt(data.DateTime.replace(/\/Date\((\d+)\)\//gi, "$1"))); but then I found this answer which will be much faster
Keith K
nice alternative...works like a charm
hallie
+1 This answer should be marked the answer. It is the most universal.
Evildonald
The replace function is safer in case MS decides to change the format.
Broam
@Broam: Both methods (the replace function and this answer) would have to change if MS changes the format.
Roy Tinker
A: 

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)

Philippe Leybaert
A: 

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

Midhat
A: 

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.

Kyle Alan Hale
A: 

Thanks for the results everyone.

Antwan W. A-Dubb
Please click "add comment" and not "add another answer" if you just have a comment.
Roy Tinker
@Tim: I totally agree, but please bear in mind that someone with rep < 50 cannot input comment everywhere.
Marcel Korpel
A: 

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.

Michael Vashchinsky
Regexp replacements are slow... It's much faster to grab the integer portion using substr(6) and pass it to parseInt() -- see my answer below.
Roy Tinker
A: 

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));
Dan Beam
Nice idea, but what if a timezone offset is included? Better to use substr(6) in that case instead of slice(6,-2) -- see my answer below.
Roy Tinker
A: 

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

StarTrekRedneck
That's not legal JSON. It will only work when eval'ing with a Javascript interpreter. But if you're using a JSON decoder, it will choke.
Roy Tinker
Agreed. And if I were just dealing with this one piece of data, I wouldn't consider it. But if I'm dealing with an object of several dates and other properties, it's easier to eval() the whole thing than pick out the properties one at a time. In the end, the root issue is the lack of a (legal) JSON date. Until that exists, we are left to our creative hacks.
StarTrekRedneck