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
Eval is not necessary. This will work fine:
ReplyDeletevar 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.
You can use this to get a date from json:
ReplyDeletevar 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.
The original example:
ReplyDelete/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)");
If you say in JavaScript,
ReplyDeletevar 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.
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:
ReplyDeleteSo 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);
}
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.
ReplyDeleteFor those using Newtonsoft Json.NET, read up on how to do it via Native JSON in IE8, Firefox 3.5 plus Json.NET.
ReplyDeleteFor 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);
Don't repeat yourself - automate date conversion using $.parseJSON()
ReplyDeleteAnswers 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.
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.
ReplyDeleteIn 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:
ReplyDelete(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.
Posting in awesome thread:
ReplyDeletevar d = new Date(parseInt('/Date(1224043200000)/'.slice(6, -2)));
alert('' + (1 + d.getMonth()) + '/' + d.getDate() + '/' + d.getFullYear().toString().slice(-2));
Every one of these answers has one thing in common: they all store dates as a single value ( usually a string ).
ReplyDeleteAnother 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.
var newDate = dateFormat(jsonDate, "mm/dd/yyyy");
ReplyDeleteare there any other option without using JQuery Libraries...?
Check up the Date ISO standard; kind of like this;
ReplyDelete"yyyy.MM.ddThh:mm"
becomes; 2008.11.20T22:18
I get the date like this:
ReplyDelete"/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.
A late post, but for those who searched this post.
ReplyDeleteImagine 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.
Check this for a generic solution for parsing date values in JSON strings:
ReplyDeletehttp://www.blog.activa.be/2010/03/12/HandlingDatesInJSONResponsesWithJQuery14TheEasyWay.aspx
(assumes you're using jQuery 1.4 or higher)
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.
ReplyDeleteMootools solution:
ReplyDeletenew 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
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)}
ReplyDeletehttp://stackoverflow.com/questions/1341719/custom-javascriptconverter-for-datetime/3930187#3930187
var obj = eval('(' + "{Date: \/Date(1278903921551)\/}".replace(/\/Date\((\d+)\)\//gi, "new Date($1)") + ')');
ReplyDeletevar dateValue = obj["Date"];
$.datepicker.formatDate('MM d,yy',new Date(parseInt(place the date that you get from the database here)));
ReplyDeleteoutput : August 30,2011
this doesnt give you the current time and date.. it displays whatever is there in your database.
Your JSON should probably be returning an object of some sort (well, a string representation thereof).
ReplyDelete"{ 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"
}
);