Fechas en formato nativo recibiendo JSON en AngularJS

Una de las arquitecturas habituales del desarrollo de aplicaciones con AngularJS se basa en la interacción con el servidor mediante un API REST junto con un intercambio de datos con JSON. Si utilizamos fechas en nuestros objectos (bastante probable) nos encontraremos con una decisión.

El formato de intercambio JSON no tiene soporte para fechas como tipo nativo. Así que si queremos transmitir fechas debemos escoger qué formato utilizar. Si no tenemos un requisito específico para un formato es conveniente utilizar el ISO 8601.

Mediante esta codificación podemos recibir las fechas en el objeto JSON como un String. A partir de ahí podemos convertirla en una fecha utilizando múltiples mecanismos. En mi caso suelo utilizar la libreria moment.js para trabajar con fechas a nivel Javascript. Convertir una fecha codificada con ISO 8601 es tan fácil como utilizar el propio constructor de moment().

En mi último proyecto he ido un paso más allá para integrar un conversor en todas las respuestas HTTP de manera que revisa todos los strings de la respuesta y, los que parecen una fecha y se pueden convertir, los sustituye por una fecha en formato nativo de Javascript.

Este es el código que prepara este mecanismo.

(function () {
  "use strict";

  var regex = /^\d{4}-\d{2}-\d{2}(?:T\d{2}:\d{2}(?::\d{2}(?:\.\d{3,9})?)?)?$/;

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

    for (var key in input) {
      if (!input.hasOwnProperty(key)) { // Ignore inherited properties
        continue;
      }

      var value = input[key];
      var match;
      // Check for string properties which look like dates.
      if (typeof value === "string" && (match = value.match(regex))) {
        var m = moment(match[0]);
        if (m.isValid()) {
          input[key] = m.toDate();
        }
      } else if (typeof value === "object") {
        // Recurse into object
        dateStringsToDates(value);
      }
    }

    return input;
  }

  angular
      .module("myApp", [])
      .factory('DateStringsToDates', function () {
        return {
          process: dateStringsToDates
        };
      })
      .config(function ($httpProvider) {
        $httpProvider.defaults.transformResponse.push(function (responseData) {
          return dateStringsToDates(responseData);
        });
      });
}());