AngularJS $http date parsing

Adds a response interceptor to $httpProvider that converts ISO 8601 date strings into Date objects.

by Annemarie Köhler

HTML

<div ng-app="app" ng-controller="DemoController">
    <form ng-submit="go()">
        <label for="date-input">Date string returned from server</label>
        <input type="text" id="date-input" ng-model="form.date" value="1984-09-25" />
        <button type="submit">Go</button>
    </form>
    <div ng-show="date">
        <p><code>response.data.date instanceof Date === {{isDate}}</code>
        </p>
        <p ng-show="isDate">Display using Angular's date filter: {{date | date:'longDate'}}</p>
    </div>
</div>

JavaScript

// Define our application module.
var app = angular.module("app", []);

// Configure the $httpProvider by adding our date transformer
app.config(["$httpProvider", function ($httpProvider) {
    $httpProvider.defaults.transformResponse.push(function(responseData){
        convertDateStringsToDates(responseData);
        return responseData;
    });
}]);

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.
        // TODO: Improve this regex to better match ISO 8601 date strings.
        if (typeof value === "string" && (match = value.match(regexIso8601))) {
            // Assume that Date.parse can parse ISO 8601 strings, or has been shimmed in older browsers to do so.
            var milliseconds = Date.parse(match[0]);
            if (!isNaN(milliseconds)) {
                input[key] = new Date(milliseconds);
            }
        } else if (typeof value === "object") {
            // Recurse into object
            convertDateStringsToDates(value);
        }
    }
}


app.controller("DemoController", ["$http", "$scope", DemoController]);

function DemoController($http, $scope) {
    $scope.form = {
        date: "1984-09-25"
    };
    $scope.go = function () {
        var request = queryServer($http, $scope.form);
        request.then(function (response) {
            $scope.isDate = response.data.date instanceof Date;
            $scope.date = response.data.date;
        });
    };
    $scope.go();
}

// Use JSFiddle's echo service to return back our test data.
function queryServer($http, responseData) {
    var json =...