jquery date - ¿Cómo formateo una fecha Microsoft JSON?




to dd/mm/yyyy (25)

Estoy tomando mi primera grieta en Ajax con jQuery. Obtengo mis datos en mi página, pero tengo algunos problemas con los datos JSON que se devuelven para los tipos de datos Fecha. Básicamente, estoy recuperando una cadena que se ve así:

/Date(1224043200000)/

De alguien totalmente nuevo a JSON: ¿Cómo formateo esto a un formato de fecha corta? ¿Debe manejarse esto en algún lugar del código jQuery? He intentado el complemento jQuery.UI.datepicker usando $.datepicker.formatDate() sin ningún éxito.

FYI: Aquí está la solución que se me ocurrió usando una combinación de las respuestas aquí:

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;
}

Esta solución obtuvo mi objeto del método de devolución de llamada y mostró las fechas en la página correctamente usando la biblioteca de formato de fecha.


Answers

Compruebe la fecha ISO estándar; algo como esto:

yyyy.MM.ddThh:mm

Se convierte en 2008.11.20T22:18 .


El ejemplo original:

/Date(1224043200000)/  

no refleja el formato utilizado por WCF al enviar fechas a través de WCF REST utilizando la serialización JSON incorporada. (Al menos en .NET 3.5, SP1)

Encontré la respuesta aquí útil, pero se requiere una pequeña edición de la expresión regular, ya que parece que el desplazamiento GMT de la zona horaria se está agregando al número devuelto (desde 1970) en WCF JSON.

En un servicio WCF tengo:

[OperationContract]
[WebInvoke(
    RequestFormat = WebMessageFormat.Json,
    ResponseFormat = WebMessageFormat.Json,
    BodyStyle = WebMessageBodyStyle.WrappedRequest
    )]
ApptVisitLinkInfo GetCurrentLinkInfo( int appointmentsId );

ApptVisitLinkInfo se define simplemente:

public class ApptVisitLinkInfo {
    string Field1 { get; set; }
    DateTime Field2 { get; set; }
    ...
}

Cuando "Field2" se devuelve como Json desde el servicio, el valor es:

/Date(1224043200000-0600)/

Observe el desplazamiento de zona horaria incluido como parte del valor.

La expresión regular modificada:

/\/Date\((.*?)\)\//gi

Es un poco más ansioso y atrapa todo entre los parens, no solo el primer número. El tiempo resultante sinze 1970, más el desplazamiento de la zona horaria se pueden incluir en la evaluación para obtener un objeto de fecha.

La línea resultante de JavaScript para el reemplazo es:

replace(/\/Date\((.*?)\)\//gi, "new Date($1)");

Terminé agregando los "caracteres en la expresión regular de Panos para deshacerme de los generados por el serializador de Microsoft para cuando se escriben objetos en un script en línea:

Entonces, si tiene una propiedad en su code-behind C # code-behind eso es algo como

protected string JsonObject { get { return jsSerialiser.Serialize(_myObject); }}

Y en tu aspx tienes

<script type="text/javascript">
    var myObject = '<%= JsonObject %>';
</script>

Obtendrías algo como

var myObject = '{"StartDate":"\/Date(1255131630400)\/"}';

Note las comillas dobles.

Para poner esto en una forma que eval deserialice correctamente, utilicé:

myObject = myObject.replace(/"\/Date\((\d+)\)\/"/g, 'new Date($1)');

Uso Prototype y para usarlo agregué.

String.prototype.evalJSONWithDates = function() {
    var jsonWithDates = this.replace(/"\/Date\((\d+)\)\/"/g, 'new Date($1)');
    return jsonWithDates.evalJSON(true);
}

Para aquellos que usan Newtonsoft Json.NET , lea cómo hacerlo a través de Native JSON en IE8, Firefox 3.5 más Json.NET .

También es útil la documentación sobre cómo cambiar el formato de las fechas escritas por Json.NET: Serialización de fechas con Json.NET

Para aquellos que son demasiado perezosos, aquí están los pasos rápidos. Como JSON tiene una implementación suelta de DateTime, debe usar el IsoDateTimeConverter() . Tenga en cuenta que desde Json.NET 4.5, el formato de fecha predeterminado es ISO, por lo que no es necesario el siguiente código.

string jsonText = JsonConvert.SerializeObject(p, new IsoDateTimeConverter());

El JSON llegará a través de

"fieldName": "2009-04-12T20:44:55"

Finalmente, algunos JavaScript para convertir la fecha ISO en una fecha de JavaScript:

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;
}

Lo usé así

$("<span />").text(isoDateReviver(item.fieldName).toLocaleString()).appendTo("#" + divName);

Publicando en hilo impresionante:

var d = new Date(parseInt('/Date(1224043200000)/'.slice(6, -2)));
alert('' + (1 + d.getMonth()) + '/' + d.getDate() + '/' + d.getFullYear().toString().slice(-2));

¿Qué pasa si .NET devuelve ...

return DateTime.Now.ToString("u"); //"2013-09-17 15:18:53Z"

Y luego en JavaScript ...

var x = new Date("2013-09-17 15:18:53Z");

Solo para agregar otro enfoque aquí, el "enfoque de garrapatas" que toma WCF es propenso a problemas con las zonas horarias si no es extremadamente cuidadoso, como se describe here y en otros lugares. Así que ahora estoy usando el formato ISO 8601 que soporta debidamente .NET y JavaScript que incluye compensaciones de zona horaria. A continuación se presentan los detalles:

En WCF / .NET:

Donde CreationDate es un System.DateTime; ToString ("o") utiliza el especificador de formato de ida y vuelta de .NET que genera una cadena de fecha compatible con ISO 8601

new MyInfo {
    CreationDate = r.CreationDate.ToString("o"),
};

En JavaScript

Justo después de recuperar el JSON, voy a arreglar las fechas para que sean objetos JavaSript Date utilizando el constructor Date que acepta una cadena de fecha ISO 8601 ...

$.getJSON(
    "MyRestService.svc/myinfo",
    function (data) {
        $.each(data.myinfos, function (r) {
            this.CreatedOn = new Date(this.CreationDate);
        });
        // Now each myinfo object in the myinfos collection has a CreatedOn field that is a real JavaScript date (with timezone intact).
       alert(data.myinfos[0].CreationDate.toLocaleString());
    }
)

Una vez que tenga una fecha de JavaScript, puede utilizar todos los métodos de fecha convenientes y confiables como toDateString , toLocaleString , etc.


No se repita, automatice la conversión de fecha usando $.parseJSON()

Las respuestas a su publicación proporcionan la conversión manual de fechas a fechas de JavaScript. He extendido $.parseJSON() jQuery solo un poco, por lo que es capaz de analizar automáticamente las fechas cuando se lo $.parseJSON() . Procesa fechas con formato ASP.NET ( /Date(12348721342)/ ), así como fechas con formato ISO ( 2010-01-01T12.34.56.789Z ) que son compatibles con funciones JSON nativas en los navegadores (y bibliotecas como json2.js).

De todas formas. Si no quieres repetir el código de conversión de la fecha una y otra vez, te sugiero que leas esta publicación del blog y obtengas el código que hará tu vida un poco más fácil.


Puedes usar esto para obtener una fecha de JSON:

var date = eval(jsonDate.replace(/\/Date\((\d+)\)\//gi, "new Date($1)"));

Y luego puede usar una secuencia de comandos de Formato de fecha de JavaScript (1.2 KB cuando está minimizado y gzipped) para mostrarlo como desee.


Esto es frustrante. Mi solución fue analizar el "/ y /" del valor generado por el JavaScriptSerializer de ASP.NET para que, aunque JSON no tenga una fecha literal, el navegador la interprete como una fecha, que es lo que realmente quiero. quiero: {"myDate":Date(123456789)}

Personalizado JavaScriptConverter para DateTime?

Debo enfatizar la exactitud del comentario de Roy Tinker. Esto no es legal JSON. Es un truco sucio y sucio en el servidor para eliminar el problema antes de que se convierta en un problema para JavaScript. Se ahogará un analizador JSON. Lo usé para despegar, pero ya no lo uso. Sin embargo, todavía siento que la mejor respuesta radica en cambiar la forma en que el servidor formatea la fecha, por ejemplo, ISO como se menciona en otra parte.


Esto también puede ayudarte.

 function ToJavaScriptDate(value) { //To Parse Date from the Returned Parsed Date
        var pattern = /Date\(([^)]+)\)/;
        var results = pattern.exec(value);
        var dt = new Date(parseFloat(results[1]));
        return (dt.getMonth() + 1) + "/" + dt.getDate() + "/" + dt.getFullYear();
    }

Cada una de estas respuestas tiene una cosa en común: todas almacenan las fechas como un solo valor (generalmente una cadena).

Otra opción es aprovechar la estructura inherente de JSON y representar una fecha como lista de números:

{ "name":"Nick",
  "birthdate":[1968,6,9] }

Por supuesto, tendría que asegurarse de que ambos extremos de la conversación estén de acuerdo con el formato (año, mes, día) y qué campos deben ser fechas, ... pero tiene la ventaja de evitar completamente el tema de la fecha conversión a cadena. Es todos los números - no hay cadenas en absoluto. Además, el uso del orden: año, mes, día también permite una clasificación adecuada por fecha.

Solo pensar fuera de lo establecido aquí: una fecha JSON no tiene que almacenarse como una cadena.

Otra ventaja de hacerlo de esta manera es que puede seleccionar de manera fácil (y eficiente) todos los registros para un año o mes dado aprovechando la forma en que CouchDB maneja las consultas en los valores de matriz.


Un post tardío, pero para aquellos que buscaron este post.

Imagina esto:

    [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");
    }

Como puede ver, estoy utilizando la función C # 3.0 para crear los genéricos "automáticos". Es un poco perezoso, pero me gusta y funciona. Solo una nota: Profile es una clase personalizada que he creado para mi proyecto de aplicación web.


En jQuery 1.5, siempre que tenga json2.js para cubrir los navegadores más antiguos, puede deserializar todas las fechas que vienen de Ajax de la siguiente manera:

(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);
        }
      }
    });
}());

Incluí la lógica que supone que envías todas las fechas desde el servidor como UTC (que deberías); el consumidor obtiene un objeto Date JavaScript que tiene el valor de marcas adecuado para reflejar esto. Es decir, llamar a getUTCHours() , etc. en la fecha devolverá el mismo valor que en el servidor, y llamar a getHours() devolverá el valor en la zona horaria local del usuario según lo determine su navegador.

Esto no tiene en cuenta el formato WCF con compensaciones de zona horaria, aunque sería relativamente fácil de agregar.


También tuve que buscar una solución a este problema y, finalmente, me encontré con moment.js, que es una buena biblioteca que puede analizar este formato de fecha y muchos más.

var d = moment(yourdatestring)

Me ahorró un poco de dolor de cabeza, así que pensé que lo compartiría contigo. :)
Puede encontrar más información al respecto aquí: http://momentjs.com/


Eval no es necesario. Esto funcionará bien:

var date = new Date(parseInt(jsonDate.substr(6)));

La función substr saca la parte "/ Date ("), y la función parseInt obtiene el entero e ignora la ") /" al final. El número resultante se pasa al constructor Fecha.

EDITAR: he intencionalmente omitido el radix (el segundo argumento a analizar); ver mi comentario a continuación . Además, estoy totalmente de acuerdo con el comentario de Rory : las fechas ISO-8601 son preferibles a este formato antiguo, por lo que este formato generalmente no debe usarse para nuevos desarrollos. Vea la excelente biblioteca Json.NET para una excelente alternativa que serializa fechas utilizando el formato ISO-8601.

Para las fechas JSON con formato ISO-8601, simplemente pase la cadena al constructor Fecha:

var date = new Date(jsonDate); //no ugly parsing needed; full timezone support

Si dices en JavaScript,

var thedate = new Date(1224043200000);
alert(thedate);

verá que es la fecha correcta y puede usarla en cualquier lugar en el código JavaScript con cualquier marco.


Agregue el plugin jQuery UI en su página:

function DateFormate(dateConvert) {
    return $.datepicker.formatDate("dd/MM/yyyy", eval('new ' + dateConvert.slice(1, -1)));
};

No pienses demasiado en esto. Como lo hemos hecho durante décadas, pase un desplazamiento numérico de la época estándar de facto del 1 de enero de 1970 a medianoche GMT / UTC / & c en número de segundos (o milisegundos) desde esta época. A JavaScript le gusta, a Java le gusta, a C le gusta, ya Internet le gusta.


Usar jQuery UI datepicker - realmente solo tiene sentido si ya está incluyendo jQuery UI:

$.datepicker.formatDate('MM d, yy', new Date(parseInt('/Date(1224043200000)/'.substr(6)))); 

salida:

15 de octubre de 2008


var obj = eval('(' + "{Date: \/Date(1278903921551)\/}".replace(/\/Date\((\d+)\)\//gi, "new Date($1)") + ')');
var dateValue = obj["Date"];

Actualizado

Tenemos una biblioteca de IU interna que tiene que lidiar con el formato JSON incorporado de ASP.NET de Microsoft, como /Date(msecs)/ , se le preguntó aquí originalmente, y el formato de fecha de la mayoría de JSON, incluyendo JSON.NET, como 2014-06-22T00:00:00.0 . Además, debemos hacer frente a la incapacidad de oldIE para hacer frente a cualquier cosa menos 3 lugares decimales .

Primero detectamos qué tipo de fecha estamos consumiendo, la analizamos en un objeto de Date normal de JavaScript, y luego lo formateamos.

1) Detectar el formato de fecha de Microsoft

// Handling of Microsoft AJAX Dates, formatted like '/Date(01238329348239)/'
function looksLikeMSDate(s) {
    return /^\/Date\(/.test(s);
}

2) Detectar formato de fecha ISO

var isoDateRegex = /^(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)(\.\d\d?\d?)?([\+-]\d\d:\d\d|Z)?$/;

function looksLikeIsoDate(s) {
    return isoDateRegex.test(s);
}

3) Formato de fecha de MS de análisis:

function parseMSDate(s) {
    // Jump forward past the /Date(, parseInt handles the rest
    return new Date(parseInt(s.substr(6)));
}

4) Analizar formato de fecha ISO.

Al menos tenemos una forma de asegurarnos de que estamos tratando con fechas ISO estándar o fechas ISO modificadas para tener siempre tres lugares de milisegundos ( ver arriba ), por lo que el código es diferente según el entorno.

4a) Analizar el formato de fecha ISO estándar, hacer frente a los problemas de oldIE:

function parseIsoDate(s) {
    var m = isoDateRegex.exec(s);

    // Is this UTC, offset, or undefined? Treat undefined as UTC.
    if (m.length == 7 ||                // Just the y-m-dTh:m:s, no ms, no tz offset - assume UTC
        (m.length > 7 && (
            !m[7] ||                    // Array came back length 9 with undefined for 7 and 8
            m[7].charAt(0) != '.' ||    // ms portion, no tz offset, or no ms portion, Z
            !m[8] ||                    // ms portion, no tz offset
            m[8] == 'Z'))) {            // ms portion and Z
        // JavaScript's weirdo date handling expects just the months to be 0-based, as in 0-11, not 1-12 - the rest are as you expect in dates.
        var d = new Date(Date.UTC(m[1], m[2]-1, m[3], m[4], m[5], m[6]));
    } else {
        // local
        var d = new Date(m[1], m[2]-1, m[3], m[4], m[5], m[6]);
    }

    return d;
}

4b) Analice el formato ISO con tres decimales milisegundos fijos, mucho más fácil:

function parseIsoDate(s) {
    return new Date(s);
}

5) Formatearlo:

function hasTime(d) {
    return !!(d.getUTCHours() || d.getUTCMinutes() || d.getUTCSeconds());
}

function zeroFill(n) {
    if ((n + '').length == 1)
        return '0' + n;

    return n;
}

function formatDate(d) {
    if (hasTime(d)) {
        var s = (d.getMonth() + 1) + '/' + d.getDate() + '/' + d.getFullYear();
        s += ' ' + d.getHours() + ':' + zeroFill(d.getMinutes()) + ':' + zeroFill(d.getSeconds());
    } else {
        var s = (d.getMonth() + 1) + '/' + d.getDate() + '/' + d.getFullYear();
    }

    return s;
}

6) Atar todo junto:

function parseDate(s) {
    var d;
    if (looksLikeMSDate(s))
        d = parseMSDate(s);
    else if (looksLikeIsoDate(s))
        d = parseIsoDate(s);
    else
        return null;

    return formatDate(d);
}

La respuesta anterior a continuación es útil para vincular este formato de fecha al propio análisis JSON de jQuery para que pueda obtener los objetos de fecha en lugar de cadenas, o si todavía está atascado en jQuery <1.5 de alguna manera.

Respuesta antigua

Si está utilizando la función Ajax de jQuery 1.4 con ASP.NET MVC, puede convertir todas las propiedades de DateTime en objetos de fecha con:

// Once
jQuery.parseJSON = function(d) {return eval('(' + d + ')');};

$.ajax({
    ...
    dataFilter: function(d) {
        return d.replace(/"\\\/(Date\(-?\d+\))\\\/"/g, 'new $1');
    },
    ...
});

En jQuery 1.5 puede evitar anular el método parseJSON globalmente utilizando la opción de convertidores en la llamada Ajax.

http://api.jquery.com/jQuery.ajax/

Desafortunadamente, tiene que cambiar a la ruta de evaluación más antigua para que las Fechas se analicen globalmente en el lugar; de lo contrario, deberá convertirlas en una base posterior de análisis caso por caso.


También puede usar la biblioteca de JavaScript http://momentjs.com/ , que es útil cuando planea lidiar con diferentes formatos localizados y realizar otras operaciones con valores de fechas:

function getMismatch(id) {
    $.getJSON("Main.aspx?Callback=GetMismatch",
    { MismatchId: id },

    function (result) {
        $("#AuthMerchId").text(result.AuthorizationMerchantId);
        $("#SttlMerchId").text(result.SettlementMerchantId);
        $("#CreateDate").text(moment(result.AppendDts).format("L"));
        $("#ExpireDate").text(moment(result.ExpiresDts).format("L"));
        $("#LastUpdate").text(moment(result.LastUpdateDts).format("L"));
        $("#LastUpdatedBy").text(result.LastUpdateNt);
        $("#ProcessIn").text(result.ProcessIn);
    }
    );
    return false;
}

Configurar la localización es tan fácil como agregar archivos de configuración (los obtiene en momentjs.com) a su proyecto y configurar el idioma:

moment.lang('de');

Tengo la fecha como esta:

"/Date(1276290000000+0300)/"

En algunos ejemplos, la fecha está en formatos ligeramente diferentes:

"/Date(12762900000000300)/"
"Date(1276290000000-0300)"

etc.

Así que se me ocurrió el siguiente RegExp:

/\/+Date\(([\d+]+)\)\/+/

y el código final es:

var myDate = new Date(parseInt(jsonWcfDate.replace(/\/+Date\(([\d+-]+)\)\/+/, '$1')));

Espero eso ayude.

Actualización: Encontré este enlace de Microsoft: ¿Cómo serializo las fechas con JSON?

Este parece ser el que todos estamos buscando.


Esta es una pregunta "¿puedes?" Y aquí hay una respuesta de "sí" .

No, no debe usar miembros de objetos duplicados para rellenar datos del canal lateral en una codificación JSON. (Consulte "Los nombres dentro de un objeto DEBEN ser únicos" en el RFC ).

Y sí, podría insertar comentarios en torno al JSON , que podría analizar.

Pero si desea una forma de insertar y extraer datos de canal lateral arbitrarios a un JSON válido, aquí hay una respuesta. Aprovechamos la representación no única de datos en una codificación JSON. Esto está permitido * en la sección dos de la RFC bajo "el espacio en blanco está permitido antes o después de cualquiera de los seis caracteres estructurales".

* El RFC solo indica "se permite el espacio en blanco antes o después de cualquiera de los seis caracteres estructurales", sin mencionar explícitamente cadenas, números, "falso", "verdadero" y "nulo". Esta omisión es ignorada en TODAS las implementaciones.

Primero, canonicaliza tu JSON reduciéndolo:

$jsonMin = json_encode(json_decode($json));

Luego codifica tu comentario en binario:

$hex = unpack('H*', $comment);
$commentBinary = base_convert($hex[1], 16, 2);

Entonces steg tu binario:

$steg = str_replace('0', ' ', $commentBinary);
$steg = str_replace('1', "\t", $steg);

Aquí está tu salida:

$jsonWithComment = $steg . $jsonMin;




jquery asp.net ajax json