Automatic JSON date parsing with AngularJS

JSON doesn't have a native date/time data-type. So you're most likely to see dates encoded as strings. A good choice of string format is ISO 8601. It's easy to parse and relatively unambiguous.

However, when it comes to working with dates in JavaScript, it's far better to work with the built-in Date object, instead of strings. Client-side code will need to convert any date strings found in JSON responses into Date objects.

Here's a function that recursively searches the properties of an object, replacing date/time strings with Date objects:

var regexIso8601 = /^(\d{4}|\+\d{6})(?:-(\d{2})(?:-(\d{2})(?:T(\d{2}):(\d{2}):(\d{2})\.(\d{1,})(Z|([\-+])(\d{2}):(\d{2}))?)?)?)?$/;

function convertDateStringsToDates(input) {
    // Ignore things that aren't objects.
    if (typeof input !== "object") return input;

    for (var key in input) {
        if (!input.hasOwnProperty(key)) continue;

        var value = input[key];
        var match;
        // Check for string properties which look like dates.
        if (typeof value === "string" && (match = value.match(regexIso8601))) {
            var milliseconds = Date.parse(match[0])
            if (!isNaN(milliseconds)) {
                input[key] = new Date(milliseconds);
            }
        } else if (typeof value === "object") {
            // Recurse into object
            convertDateStringsToDates(value);
        }
    }
}

Instead of using this function manually each time we make an AJAX call, we'd rather wire it into the default AJAX processing i.e. "set it and forget it". AngularJS makes this easy by using HTTP response interceptors.

First, let's assume we have a basic AngularJS application module:

var app = angular.module("app", []);

We can configure the $httpProvider.defaults by adding our response transformer, so it'll be used everytime an HTTP request is made using the $http service. Note that this is also how Angular is able to parse JSON response strings into objects for us.

app.config(["$httpProvider", function ($httpProvider) {
     $httpProvider.defaults.transformResponse.push(function(responseData){
        convertDateStringsToDates(responseData);
        return responseData;
    });
}]);

We can now make HTTP requests using the $http service and know that any date-strings will have already been converted into Date objects.

app.controller("MyController", ["$scope", "$http", function($scope, $http) {
    $scope.go = function() {
        $http.get("/foo").then(function(response) {
            // date-string properties of `response.data` will now be Date objects.
        };
    };
}]);

Working Demo

Check out the AngularJS $http documentation for more details about transforming HTTP requests and responses.

Would you like access to the sample code repository?

Subscribe to my web development mailing list.

No spam, just occasional web development tips, posts and sample code. Unsubscribe at any time.

Comments
blog comments powered by Disqus