¿Cómo formateo una fecha de Microsoft JSON?

Estoy tomando mi primera oportunidad en Ajax con jQuery. Estoy obteniendo mis datos en mi página, pero estoy teniendo problemas con los datos JSON que se devuelven para los tipos de datos de fecha. Básicamente, estoy recuperando una cadena que se ve así:

/Date(1224043200000)/ 

De alguien totalmente nuevo a JSON: ¿cómo puedo formatear esto en un formato de fecha corta? ¿Se debe manejar esto en algún lugar del código jQuery? jQuery.UI.datepicker plugin 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 callback y mostró las fechas en la página correctamente utilizando la biblioteca de formato de fecha.

Eval no es necesario. Esto funcionará bien:

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

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

EDITAR: he dejado intencionalmente la raíz (el segundo argumento para analizar); mira mi comentario a continuación . Además, estoy completamente de acuerdo con el comentario de Rory : las fechas ISO-8601 son preferibles a este formato anterior, por lo que este formato generalmente no debe usarse para nuevos desarrollos. Consulte la excelente biblioteca Json.NET para obtener una excelente alternativa que serializa las fechas usando el formato ISO-8601.

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

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

Puede usar esto para obtener una fecha de JSON:

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

Y luego puede usar un script JavaScript Date Format (1.2 KB cuando está minificado y gzip) para mostrarlo como lo desee.

Para quienes usan Newtonsoft Json.NET , lean sobre 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 vagos, aquí están los pasos rápidos. Como JSON tiene una implementación suelta de DateTime, debe usar 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 vendrá como

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

Finalmente, algunos JavaScript para convertir la fecha ISO a 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í

 $("").text(isoDateReviver(item.fieldName).toLocaleString()).appendTo("#" + divName); 

El ejemplo original:

 /Date(1224043200000)/ 

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

Encontré la respuesta aquí útil, pero se requiere una ligera edición de la expresión regular, ya que parece que la compensación de la zona horaria GMT se agrega al número devuelto (desde 1970) en WCF JSON.

En un servicio de 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 del servicio, el valor es:

 /Date(1224043200000-0600)/ 

Observe la compensación de zona horaria incluida 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 alimentar en la evaluación para obtener un objeto de fecha.

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

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

No se repita: automatice la conversión de fechas usando $.parseJSON()

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

De todas formas. Si no desea repetir el código de conversión de la fecha una y otra vez, le sugiero que lea esta publicación de blog y obtenga el código que le facilitará la vida.

Si dices en JavaScript,

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

Verás que es la fecha correcta, y puedes usarla en cualquier parte del código JavaScript con cualquier marco.

Haga clic aquí para consultar la demostración

JavaScript / jQuery

 var = MyDate_String_Value = "/Date(1224043200000)/" var value = new Date ( parseInt(MyDate_String_Value.replace(/(^.*\()|([+-].*$)/g, '')) ); var dat = value.getMonth() + 1 + "/" + value.getDate() + "/" + value.getFullYear(); 

Resultado – “15/10/2008”

Actualizado

Tenemos una biblioteca interna de UI que tiene que lidiar con el formato JSON incorporado de ASP.NET de Microsoft, como /Date(msecs)/ , que se le preguntó originalmente aquí, y la mayoría del formato de fecha de JSON, incluidos los de JSON.NET, como 2014-06-22T00:00:00.0 . Además, tenemos que hacer frente a la incapacidad de OldIE para hacer frente a cualquier cosa que no sean 3 decimales .

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

1) Detecta el formato de Microsoft Date

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

2) Detecta el 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 Parse MS:

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

4) Analizar el formato de fecha ISO.

Al menos tenemos una manera de asegurarnos de que estamos tratando con fechas ISO estándar o fechas ISO modificadas para tener siempre lugares de tres milisegundos ( ver arriba ), por lo que el código es diferente dependiendo del 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 ym-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) Analizar el formato ISO con un decimal fijo de tres milisegundos, 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) Ate todo:

 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 siguiente respuesta anterior es útil para vincular este formato de fecha en el propio análisis JSON de jQuery para que pueda obtener objetos de fecha en lugar de cadenas, o si todavía está atrapado en jQuery <1.5 de alguna manera.

Vieja respuesta

Si está utilizando la función Ajax de jQuery 1.4 con ASP.NET MVC, puede convertir todas las propiedades DateTime en objetos Date 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 mediante el uso de la opción conversores en la llamada Ajax.

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

Lamentablemente, debe cambiar a la ruta eval más antigua para que las fechas se analicen globalmente en el lugar; de lo contrario, deberá convertirlas en un análisis caso por caso posterior.

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 mucho más.

 var d = moment(yourdatestring) 

Me ahorró un dolor de cabeza, así que pensé en compartirlo contigo. 🙂
Puede encontrar más información al respecto aquí: http://momentjs.com/

Terminé agregando los “caracteres” en la expresión regular de Panos para deshacerme de los generados por el serializador de Microsoft al escribir objetos en un guión en línea:

Entonces, si tiene una propiedad en su código C # detrás, eso es algo así como

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

Y en tu aspx tienes

  

Tendrás algo así como

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

Observe las comillas dobles.

Para obtener esto en una forma que eval se deserializará 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); } 

No hay un tipo de fecha incorporada en JSON . Esto se parece a la cantidad de segundos / milisegundos de alguna época. Si conoce la época, puede crear la fecha agregando la cantidad de tiempo adecuada.

En jQuery 1.5, siempre que tenga json2.js para cubrir navegadores antiguos, puede deserializar todas las fechas provenientes 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 asume que envías todas las fechas desde el servidor como UTC (que deberías); el consumidor obtiene un objeto JavaScript Date que tiene el valor adecuado para reflejar esto. Es decir, al llamar a getUTCHours() , etc. en la fecha devolverá el mismo valor que tenía en el servidor, y al 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.

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

Usar jQuery UI datepicker: realmente solo tiene sentido si ya incluye la interfaz de usuario de jQuery:

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

salida:

15 de octubre de 2008

Todas estas respuestas tienen una cosa en común: todas almacenan fechas como un valor único (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, debe asegurarse de que ambos extremos de la conversación acuerden el formato (año, mes, día) y qué campos deben ser fechas, pero tiene la ventaja de evitar por completo el tema de la fecha. conversión a cadena. Son todos los números, sin ataduras. Además, el uso del pedido: año, mes, día también permite una clasificación adecuada por fecha.

Solo pensar fuera de la caja aquí – una fecha JSON no tiene que ser almacenada como una cadena.

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

Publicar en un hilo increíble:

 var d = new Date(parseInt('/Date(1224043200000)/'.slice(6, -2))); alert('' + (1 + d.getMonth()) + '/' + d.getDate() + '/' + d.getFullYear().toString().slice(-2)); 
 var newDate = dateFormat(jsonDate, "mm/dd/yyyy"); 

¿Hay alguna otra opción sin usar la biblioteca jQuery?

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

En WCF / .NET:

Donde CreationDate es un System.DateTime; ToString (“o”) está utilizando 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 de Fecha JavaSript usando el constructor Fecha 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 usar todos los métodos de fecha convenientes y fiables, como toDateString , toLocaleString , etc.

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

Comprueba la fecha del estándar ISO; tipo de esto:

 yyyy.MM.ddThh:mm 

Se convierte en 2008.11.20T22:18 .

Obtengo la fecha así:

 "/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.

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

JavaScriptConverter personalizado para DateTime?

Debo enfatizar la precisión del comentario de Roy Tinker. Esto no es JSON legal. 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 uso esto. Sin embargo, todavía siento que la mejor respuesta está en cambiar la forma en que el servidor da formato a la fecha, por ejemplo, ISO como se menciona en otro lugar.

Agregue el complemento jQuery UI en su página:

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

A continuación se muestra una solución bastante simple para analizar las fechas JSON. Use las siguientes funciones según su requerimiento. Solo necesita pasar el formato JSON Fecha que se obtuvo como un parámetro para las siguientes funciones:

 function JSONDate(dateStr) { var m, day; jsonDate = dateStr; var d = new Date(parseInt(jsonDate.substr(6))); m = d.getMonth() + 1; if (m < 10) m = '0' + m if (d.getDate() < 10) day = '0' + d.getDate() else day = d.getDate(); return (m + '/' + day + '/' + d.getFullYear()) } function JSONDateWithTime(dateStr) { jsonDate = dateStr; var d = new Date(parseInt(jsonDate.substr(6))); var m, day; m = d.getMonth() + 1; if (m < 10) m = '0' + m if (d.getDate() < 10) day = '0' + d.getDate() else day = d.getDate(); var formattedDate = m + "/" + day + "/" + d.getFullYear(); var hours = (d.getHours() < 10) ? "0" + d.getHours() : d.getHours(); var minutes = (d.getMinutes() < 10) ? "0" + d.getMinutes() : d.getMinutes(); var formattedTime = hours + ":" + minutes + ":" + d.getSeconds(); formattedDate = formattedDate + " " + formattedTime; return formattedDate; } 

Una publicación tardía, pero para aquellos que buscaron esta publicación.

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 de C # 3.0 para crear los generics “automáticos”. Es un poco flojo, pero me gusta y funciona. Solo una nota: Profile es una clase personalizada que he creado para mi proyecto de aplicación web.

Solución Mootools:

 new Date(Date(result.AppendDts)).format('%x') 

Requiere mootools-más. Probado usando mootools-1.2.3.1-more en Firefox 3.6.3 e IE 7.0.5730.13

También puede usar la biblioteca de JavaScript momento.js , que es útil cuando planea hacer frente a 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'); 

FYI, para cualquier persona que use Python en el lado del servidor: datetime.datetime (). Ctime () devuelve una cadena que es nativamente analizable por “nueva Fecha ()”. Es decir, si crea una nueva instancia de datetime.datetime (como datetime.datetime.now), la cadena se puede incluir en la cadena JSON, y luego esa cadena se puede pasar como primer argumento al constructor de la fecha. Todavía no he encontrado ninguna excepción, pero tampoco la he probado con demasiada rigurosidad.

What if .NET returns…

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

And then in JavaScript…

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

This may can also help you.

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