Angular.js format date from json object
My json response look like this:
[{"Id":"dab4580b-e24d-49f8-9fd5-2e968b10d3b5","Title":"MVVM-Sidekick 入精","CreatedOn":"\/Date(1390272893353)\/","IsChecked":false},{"Id":"66a0f134-e240-4cc4-96fa-ac3807853ca7","Title":"Windows Phone 开发入精","CreatedOn":"\/Date(1390018447080)\/","IsChecked":false}]
the “CreatedOn” date is in this kind of format: ‘/Date(1390272893353)/’
when I bind this result to html table, the date cannot be formatted:
<td>{{item.CreatedOn | date: 'yyyy-MM-dd HH:mm'}}</td>
still gives me:
/Date(1390272893353)/
I don’t want to change any code on the server side (don’t modify the json string), what’s the best way to format this date?
I actually combined the answers from @Charminbear and @Nikos ending up in this filter which works quite nice and is quite clear without the regex:
myApp.filter("jsDate", function () {
return function (x) {
return new Date(parseInt(x.substr(6)));
};
});
This makes it possible to write
{{ $scope.item.CreatedOn | jsDate | date:"yyyy-MM-dd" }}
One option is to write another filter and put it in the chain. E.g.:
app.filter("mydate", function() {
var re = /\/Date\(([0-9]*)\)\//;
return function(x) {
var m = x.match(re);
if( m ) return new Date(parseInt(m[1]));
else return null;
};
});
Basically it uses the regular expression to parse the string and make a Date
(if the format is different than the one shown, you will have to tweak the regular expression).
Use it as:
<td>{{item.CreatedOn | mydate | date: 'yyyy-MM-dd HH:mm'}}</td>
I know I’m late for the party. But I want to tell what helped me was :-
<td>{{item.yourdatefield.slice(6,-2) | date:'dd-MMM-yyyy' }}</td>
Hope it’ll help lazy coders like Me. 🙂
The Angular Date-Filter expects a JS-Date. So you need to parse the JSON Date before giving it to the filter.
Try this:
<td>{{item.CreatedOnParsed | date: 'yyyy-MM-dd HH:mm'}}</td>
And in your callback-method of the response, do something like:
$scope.item.CreatedOnParsed = new Date(parseInt(item.CreatedOn.substr(6)));
as it is shown in this Answer
EDIT
As is just saw by the comments of your post, even just the timestamp is enough for the Date-Filter, so even this should be enough:
$scope.item.CreatedOnParsed = item.CreatedOn.substr(6);
//input - "DocDate":"\/Date(1127318400000-0000)\/"
-------
<tr dir-paginate="user in SalesOrder>
<td>{{user.DocDate | jsonDate}}</td>
</tr>
controller
----------
app.filter('jsonDate', ['$filter', function ($filter) {
return function (input, format) {
return (input)
? $filter('date')(parseInt(input.substr(6)), format)
: '';
};
}]);
Another, possibly better option, is to parse the date as you recieve the JSON.
I use the following function:
(function() {
if (JSON && !JSON.parseWithDate) {
JSON.parseWithoutDate = JSON.parse; //Store the original JSON.parse function
var reISO = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/;
var reMsAjax = /^\/Date\((d|-|.*)\)[\/|\\]$/;
JSON.parseWithDate = function (json) {
/// <summary>
/// parses a JSON string and turns ISO or MSAJAX date strings
/// into native JS date objects
/// </summary>
/// <param name="json" type="var">json with dates to parse</param>
/// </param>
/// <returns type="value, array or object" />
try {
var res = JSON.parseWithoutDate(json,
function (key, value) {
if (typeof value === 'string') {
var a = reISO.exec(value);
if (a)
return new Date(Date.UTC(+a[1], +a[2] - 1,
+a[3], +a[4], +a[5], +a[6]));
a = reMsAjax.exec(value);
if (a) {
var b = a[1].split(/[-+,.]/);
return new Date(b[0] ? +b[0] : 0 - +b[1]);
}
}
return value;
});
return res;
} catch (e) {
// orignal error thrown has no error message so rethrow with message
throw new Error("JSON content could not be parsed");
return null;
}
};
JSON.dateStringToDate = function (dtString) {
/// <summary>
/// Converts a JSON ISO or MSAJAX string into a date object
/// </summary>
/// <param name="" type="var">Date String</param>
/// <returns type="date or null if invalid" />
var a = reISO.exec(dtString);
if (a)
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3],
+a[4], +a[5], +a[6]));
a = reMsAjax.exec(dtString);
if (a) {
var b = a[1].split(/[-,.]/);
return new Date(+b[0]);
}
return null;
};
JSON.stringifyWcf = function (json) {
/// <summary>
/// Wcf specific stringify that encodes dates in the
/// a WCF compatible format ("/Date(9991231231)/")
/// Note: this format works ONLY with WCF.
/// ASMX can use ISO dates as of .NET 3.5 SP1
/// </summary>
/// <param name="key" type="var">property name</param>
/// <param name="value" type="var">value of the property</param>
return JSON.stringify(json, function (key, value) {
if (typeof value == "string") {
var a = reISO.exec(value);
if (a) {
var val="/Date(" +
new Date(Date.UTC(+a[1], +a[2] - 1,
+a[3], +a[4],
+a[5], +a[6])).getTime() + ')/';
this[key] = val;
return val;
}
}
return value;
})
};
//Make Date parsing the default
JSON.parse = JSON.parseWithDate;
}
})();
Which is taken from here: http://codepaste.net/i89xhc, except that I overwrite the standard JSON.parse function with this version that parses the date. This means that Angular will parse ASMX dates automatically from all JSON it sees.
You could also write a custom transform using angular $http transformations. See: https://docs.angularjs.org/api/ng/service/$http
Assuming that is a .net JSON date and you are using moment.js. Then leverage it’s functionality (defined here ) into a filter
myApp.filter('JSONdate', [
'$filter', function ($filter) {
return function (input, appformat) {
if (input != null) {
return moment(input).format(appformat);
// use the line below if you want to leverage the standard date filter on top of this
// return $filter('date')(new Date(moment(input)), appformat);
} else {
return '';
}
};
}])