Formato de data do ASP.NET MVC JsonResult

Eu tenho uma ação de controlador que efetivamente simplesmente retorna um JsonResult do meu modelo. Então, no meu método eu tenho algo parecido com o seguinte:

return new JsonResult(myModel); 

Isso funciona bem, exceto por um problema. Há uma propriedade de data no modelo e isso parece ser retornado no resultado do Json da seguinte forma:

 "\/Date(1239018869048)\/" 

Como devo estar lidando com datas para que elas sejam retornadas no formato que eu preciso? Ou como eu manipulo esse formato acima no script?

Apenas para expandir a resposta da casperOne .

A especificação JSON não considera os valores de data. MS teve que fazer uma chamada, e o caminho que escolheram foi explorar um pequeno truque na representação javascript de strings: a string literal “/” é a mesma que “\ /”, e uma string literal nunca será serializada para ” \ / “(mesmo” \ / “deve ser mapeado para” \\ / “).

Consulte http://msdn.microsoft.com/en-us/library/bb299886.aspx#intro_to_json_topic2 para obter uma explicação melhor (role para baixo até “From JavaScript Literals to JSON”)

Um dos pontos doloridos do JSON é a falta de um literal de data / hora. Muitas pessoas ficam surpresas e desapontadas ao saber disso quando encontram pela primeira vez o JSON. A explicação simples (consolar ou não) para a ausência de um literal de data / hora é que o JavaScript nunca teve um deles: O suporte para valores de data e hora em JavaScript é inteiramente fornecido através do object Date. A maioria dos aplicativos que usam JSON como formato de dados, portanto, geralmente tendem a usar uma string ou um número para expressar valores de data e hora. Se uma string for usada, geralmente você pode esperar que ela esteja no formato ISO 8601. Se um número é usado, em vez disso, o valor é normalmente usado para significar o número de milissegundos no UTC (Universal Coordinated Time) desde epoch, em que epoch é definido como meia-noite de 1 de janeiro de 1970 (UTC). Novamente, isso é uma mera convenção e não faz parte do padrão JSON. Se você estiver trocando dados com outro aplicativo, precisará verificar sua documentação para ver como ele codifica valores de data e hora em um literal JSON. Por exemplo, o ASP.NET AJAX da Microsoft não usa nenhuma das convenções descritas. Em vez disso, ele codifica os valores .NET DateTime como uma string JSON, em que o conteúdo da string é / Date (ticks) / e onde os ticks representam milissegundos desde epoch (UTC). Então, 29 de novembro de 1989, 4:55:30, em UTC, está codificado como “\ / Date (628318530718) \ /”.

Uma solução seria apenas analisar:

 value = new Date(parseInt(value.replace("/Date(", "").replace(")/",""), 10)); 

No entanto, ouvi dizer que há uma configuração em algum lugar para obter o serializador para saída de objects DateTime com a new Date(xxx) syntax de new Date(xxx) . Vou tentar descobrir isso.


O segundo parâmetro de JSON.parse() aceita uma function reviver onde prescreve como o valor originalmente produzido por, antes de ser retornado.

Aqui está um exemplo para a data:

 var parsed = JSON.parse(data, function(key, value) { if (typeof value === 'string') { var d = /\/Date\((\d*)\)\//.exec(value); return (d) ? new Date(+d[1]) : value; } return value; }); 

Veja os documentos de JSON.parse ()

Aqui está a minha solução em Javascript – muito parecido com o JPot, mas mais curto (e possivelmente um pouco mais rápido):

 value = new Date(parseInt(value.substr(6))); 

“value.substr (6)” retira a parte “/ Date (“, e a function parseInt ignora os caracteres não numéricos que ocorrem no final.

EDIT: intencionalmente deixei de fora o radix (o segundo argumento para parseInt); veja meu comentário abaixo . Além disso, observe que as datas ISO-8601 são preferidas em relação a esse formato antigo – portanto, esse formato geralmente não deve ser usado para novos desenvolvimentos. Veja a excelente biblioteca Json.NET para uma ótima alternativa que serializa datas usando o formato ISO-8601.

Para datas JSON formatadas com ISO-8601, apenas passe a string para o construtor Date:

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

Há um pouco de respostas para lidar com o lado do cliente, mas você pode alterar o lado do servidor de saída, se desejar.

Existem algumas maneiras de abordar isso, vou começar com o básico. Você terá que subclassificar a class JsonResult e replace o método ExecuteResult. A partir daí, você pode adotar algumas abordagens diferentes para alterar a serialização.

Abordagem 1: A implementação padrão usa o JsonScriptSerializer . Se você der uma olhada na documentação, você pode usar o método RegisterConverters para adicionar JavaScriptConverters personalizados. Existem alguns problemas com isso: O JavaScriptConverter é serializado para um dictionary, ou seja, leva um object e serializa para um dictionary Json. Para tornar o object serializado em uma string, é necessário um pouco de hack, veja post . Esse hack específico também escapingá da string.

 public class CustomJsonResult : JsonResult { private const string _dateFormat = "yyyy-MM-dd HH:mm:ss"; public override void ExecuteResult(ControllerContext context) { if (context == null) { throw new ArgumentNullException("context"); } HttpResponseBase response = context.HttpContext.Response; if (!String.IsNullOrEmpty(ContentType)) { response.ContentType = ContentType; } else { response.ContentType = "application/json"; } if (ContentEncoding != null) { response.ContentEncoding = ContentEncoding; } if (Data != null) { JavaScriptSerializer serializer = new JavaScriptSerializer(); // Use your custom JavaScriptConverter subclass here. serializer.RegisterConverters(new JavascriptConverter[] { new CustomConverter }); response.Write(serializer.Serialize(Data)); } } } 

Abordagem 2 (recomendado): A segunda abordagem é começar com o JsonResult substituído e ir com outro serializador Json, no meu caso o serializador Json.NET . Isso não requer o hackery da abordagem 1. Aqui está minha implementação da subclass JsonResult:

 public class CustomJsonResult : JsonResult { private const string _dateFormat = "yyyy-MM-dd HH:mm:ss"; public override void ExecuteResult(ControllerContext context) { if (context == null) { throw new ArgumentNullException("context"); } HttpResponseBase response = context.HttpContext.Response; if (!String.IsNullOrEmpty(ContentType)) { response.ContentType = ContentType; } else { response.ContentType = "application/json"; } if (ContentEncoding != null) { response.ContentEncoding = ContentEncoding; } if (Data != null) { // Using Json.NET serializer var isoConvert = new IsoDateTimeConverter(); isoConvert.DateTimeFormat = _dateFormat; response.Write(JsonConvert.SerializeObject(Data, isoConvert)); } } } 

Exemplo de uso:

 [HttpGet] public ActionResult Index() { return new CustomJsonResult { Data = new { users=db.Users.ToList(); } }; } 

Créditos adicionais: James Newton-King

Moment.js é uma extensa biblioteca datetime que também suporta isso. http://momentjs.com/docs/#/parsing/asp-net-json-dates/

ex: moment (“/ Data (1198908717056-0700) /”)

Isso pode ajudar. saída plunker

Usando o jQuery para converter datas automaticamente com $.parseJSON

Nota : esta resposta fornece uma extensão jQuery que adiciona suporte automático ao formato de data ISO e .net.

Como você está usando o Asp.net MVC, suspeito que esteja usando o jQuery no lado do cliente. Eu sugiro que você leia este post que tem código como usar $.parseJSON para converter datas automaticamente para você.

O Code suporta datas formatadas pelo Asp.net como as que você mencionou, bem como datas formatadas em ISO. Todas as datas serão automaticamente formatadas para você usando $.parseJSON() .

Descobri que criar um novo JsonResult e retornando que é insatisfatório – ter que replace todas as chamadas para return Json(obj) com return new MyJsonResult { Data = obj } é uma dor.


Então eu imaginei, por que não apenas seqüestrar o JsonResult usando um ActionFilter :

 public class JsonNetFilterAttribute : ActionFilterAttribute { public override void OnActionExecuted(ActionExecutedContext filterContext) { if (filterContext.Result is JsonResult == false) { return; } filterContext.Result = new JsonNetResult( (JsonResult)filterContext.Result); } private class JsonNetResult : JsonResult { public JsonNetResult(JsonResult jsonResult) { this.ContentEncoding = jsonResult.ContentEncoding; this.ContentType = jsonResult.ContentType; this.Data = jsonResult.Data; this.JsonRequestBehavior = jsonResult.JsonRequestBehavior; this.MaxJsonLength = jsonResult.MaxJsonLength; this.RecursionLimit = jsonResult.RecursionLimit; } public override void ExecuteResult(ControllerContext context) { if (context == null) { throw new ArgumentNullException("context"); } var isMethodGet = string.Equals( context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase); if (this.JsonRequestBehavior == JsonRequestBehavior.DenyGet && isMethodGet) { throw new InvalidOperationException( "GET not allowed! Change JsonRequestBehavior to AllowGet."); } var response = context.HttpContext.Response; response.ContentType = string.IsNullOrEmpty(this.ContentType) ? "application/json" : this.ContentType; if (this.ContentEncoding != null) { response.ContentEncoding = this.ContentEncoding; } if (this.Data != null) { response.Write(JsonConvert.SerializeObject(this.Data)); } } } } 

Isso pode ser aplicado a qualquer método que retorne um JsonResult para usar o JSON.Net:

 [JsonNetFilter] public ActionResult GetJson() { return Json(new { hello = new Date(2015, 03, 09) }, JsonRequestBehavior.AllowGet) } 

que responderá com

 {"hello":"2015-03-09T00:00:00+00:00"} 

como desejado!


Você pode, se não se importar de chamar a comparação, a cada solicitação, adicione isso ao seu FilterConfig :

 // ... filters.Add(new JsonNetFilterAttribute()); 

e todo o seu JSON será agora serializado com JSON.Net em vez do JavaScriptSerializer integrado.

A comunicação do Ajax entre o cliente e o servidor geralmente envolve dados no formato JSON. Enquanto o JSON funciona bem para strings, números e booleanos, pode representar algumas dificuldades para datas devido à maneira como o ASP.NET as serializa. Como não possui nenhuma representação especial para datas, elas são serializadas como strings simples. Como uma solução, o mecanismo de serialização padrão do ASP.NET Web Forms e MVC serializa as datas em um formato especial – / Date (ticks) / – onde ticks é o número de milissegundos desde 1º de janeiro de 1970.

Este problema pode ser resolvido de duas maneiras:

lado do cliente

Converta a string de data recebida em um número e crie um object de data usando o construtor da class de data com os ticks como parâmetro.

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

}

lado do servidor

A solução anterior usa um script do lado do cliente para converter a data em um object JavaScript Date. Você também pode usar o código do lado do servidor que serializa as instâncias .NET DateTime no formato de sua escolha. Para realizar essa tarefa, você precisa criar seu próprio ActionResult e depois serializar os dados da maneira que desejar.

referência: http://www.developer.com/net/dealing-with-json-dates-in-asp.net-mvc.html

Eu tive o mesmo problema e em vez de retornar o valor de data real eu usei ToString (“dd MMM yyyy”) nele. Em seguida, no meu javascript eu usei nova data (valor de dados), onde o valor de dados pode ser “01 jan 2009”.

Veja este tópico:

http://forums.asp.net/p/1038457/1441866.aspx#1441866

Basicamente, embora o formato Date () seja um javascript válido, ele NÃO é um JSON válido (existe uma diferença). Se você quiser o formato antigo, provavelmente terá que criar uma fachada e transformar o valor por conta própria, ou encontrar uma maneira de obter o serializador do seu tipo no JsonResult e usá-lo em um formato personalizado para datas.

Não é a maneira mais elegante, mas isso funcionou para mim:

 var ms = date.substring(6, date.length - 2); var newDate = formatDate(ms); function formatDate(ms) { var date = new Date(parseInt(ms)); var hour = date.getHours(); var mins = date.getMinutes() + ''; var time = "AM"; // find time if (hour >= 12) { time = "PM"; } // fix hours format if (hour > 12) { hour -= 12; } else if (hour == 0) { hour = 12; } // fix minutes format if (mins.length == 1) { mins = "0" + mins; } // return formatted date time string return date.getMonth() + 1 + "/" + date.getDate() + "/" + date.getFullYear() + " " + hour + ":" + mins + " " + time; } 

Eu tenho trabalhado em uma solução para este problema, pois nenhuma das respostas acima me ajudou de verdade. Eu estou trabalhando com o calendar semana jquery e precisava de minhas datas para ter informações de fuso horário no servidor e localmente na página. Depois de um pouco de pesquisa, descobri uma solução que pode ajudar os outros.

Estou usando o asp.net 3.5, vs 2008, asp.net MVC 2 e calendar de semana jquery,

Primeiro, estou usando uma biblioteca escrita por Steven Levithan que ajuda a lidar com datas no lado do cliente, a biblioteca de datas de Steven Levithan . O formato isoUtcDateTime é perfeito para o que eu precisava. Na minha chamada jquery AJAX eu uso a function de formatação fornecida com a biblioteca com o formato isoUtcDateTime e quando a chamada ajax atinge meu método de ação, o tipo de data e hora é definido como local e reflete a hora do servidor.

Quando envio datas para a minha página via AJAX, eu as envio como strings de texto formatando as datas usando “ddd, dd MMy aaaa HH ‘:’ mm ‘:’ ss ‘GMT’zzzz”. Este formato é facilmente convertido pelo lado do cliente

 var myDate = new Date(myReceivedDate); 

Aqui está minha solução completa menos a fonte de Steve Levithan, que você pode baixar:

Controlador:

 public class HomeController : Controller { public const string DATE_FORMAT = "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'zzzz"; public ActionResult Index() { ViewData["Message"] = "Welcome to ASP.NET MVC!"; return View(); } public ActionResult About() { return View(); } public JsonResult GetData() { DateTime myDate = DateTime.Now.ToLocalTime(); return new JsonResult { Data = new { myDate = myDate.ToString(DATE_FORMAT) } }; } public JsonResult ReceiveData(DateTime myDate) { return new JsonResult { Data = new { myDate = myDate.ToString(DATE_FORMAT) } }; } } 

Javascript:

  

Espero que este exemplo rápido ajude os outros na mesma situação em que eu estava. Neste momento, parece funcionar muito bem com a serialização do Microsoft JSON e mantém minhas datas corretas em fusos horários.

A melhor maneira de lidar com datas em knockoutjs é usar biblioteca de momentos e lidar com datas como chefe. Você pode facilmente lidar com datas como / Data (-62135578800000) /. Não há necessidade de se preocupar de como sua data de serialização no controlador.

 function jsonToDate(date,format) { return moment(date).format(format); } 

usá-lo como

 var formattedDate = jsonToDate(date,'MM/DD/YYYY') 

O momentjs suporta muitos formatos de data e hora e funções utilitárias em datas.

Formate a data na consulta.

 var _myModel = from _m in model.ModelSearch(word) select new { date = ((DateTime)_m.Date).ToShortDateString() }; 

O único problema com essa solução é que você não obterá nenhum resultado se QUALQUER um dos valores de data for nulo. Para contornar isso, você poderia colocar instruções condicionais em sua consulta ANTES de selecionar a data que ignora datas nulos ou você poderia configurar uma consulta para obter todos os resultados e, em seguida, percorrer todas essas informações usando um loop foreach e atribuir um valor para todas as datas que são nulas ANTES de você fazer o seu SELECT novo.

Exemplo de ambos:

 var _test = from _t in adc.ItemSearchTest(word) where _t.Date != null select new { date = ((DateTime)_t.Date).ToShortDateString() }; 

A segunda opção requer outra consulta inteiramente para que você possa atribuir valores a todos os nulos. Este e o loop foreach teriam que ser ANTES de sua consulta que seleciona os valores.

 var _testA = from _t in adc.ItemSearchTest(word) select _i; foreach (var detail in _testA) { if (detail.Date== null) { detail.Date= Convert.ToDateTime("1/1/0001"); } } 

Apenas uma ideia que achei mais fácil do que todos os exemplos de javascript.

Você pode usar este método:

 String.prototype.jsonToDate = function(){ try{ var date; eval(("date = new " + this).replace(/\//g,'')); return date; } catch(e){ return new Date(0); } }; 

adicione o plugin jquery ui na sua página.

 function JsonDateFormate(dateFormate, jsonDateTime) { return $.datepicker.formatDate(dateFormate, eval('new ' + jsonDateTime.slice(1, -1))); }; 

Ele retorna o formato de data do servidor. Você precisa definir sua própria function.

 function jsonDateFormat(jsonDate) { // Changed data format; return (new Date(parseInt(jsonDate.substr(6)))).format("mm-dd-yyyy / h:MM tt"); 

};

Aqui está um código JavaScript que eu escrevi que define um valor de uma data passada do ASP.NET MVC.

  var setDate = function (id, d) { if (d !== undefined && d !== null) { var date = new Date(parseInt(d.replace("/Date(", "").replace(")/", ""), 10)); var day = ('0' + date.getDate()).slice(-2); var month = ('0' + (date.getMonth() + 1)).slice(-2); var parsedDate = date.getFullYear() + "-" + (month) + "-" + (day); $(id).val(parsedDate); } }; 

Você chama essa function assim:

 setDate('#productCommissionStartDate', data.commissionStartDate); 

Onde commissionStartDate é a data JSON passada pelo MVC.

Não é por nada, mas há outro caminho. Primeiro, construa sua consulta LINQ. Em seguida, construa uma consulta do resultado Enumerado e aplique o tipo de formatação para você.

 var query = from t in db.Table select new { t.DateField }; var result = from c in query.AsEnumerable() select new { c.DateField.toString("dd MMM yyy") }; 

Eu tenho que dizer, o passo extra é chato, mas funciona bem.

O que funcionou para mim foi criar um viewmodel que contivesse a propriedade date como uma string. Atribuindo a propriedade DateTime do modelo de domínio e chamando o .ToString () na propriedade date ao atribuir o valor ao viewmodel.

Um resultado JSON de um método de ação do MVC retornará a data em um formato compatível com a exibição.

Visualizar Modelo

 public class TransactionsViewModel { public string DateInitiated { get; set; } public string DateCompleted { get; set; } } 

Modelo de Domínio

 public class Transaction{ public DateTime? DateInitiated {get; set;} public DateTime? DateCompleted {get; set;} } 

Método de ação do controlador

 public JsonResult GetTransactions(){ var transactions = _transactionsRepository.All; var model = new List(); foreach (var transaction in transactions) { var item = new TransactionsViewModel { ............... DateInitiated = transaction.DateInitiated.ToString(), DateCompleted = transaction.DateCompleted.ToString(), }; model.Add(item); } return Json(model, JsonRequestBehavior.AllowGet); } 

Sobrescreva os controladores Json / JsonResult para retornar JSON.Net:

Isso funciona um deleite

Irritante, não é?

Minha solução foi alterar meu serviço WCF para que ele retornasse o DateTimes em um formato mais legível (não-Microsoft). Observe abaixo, o ” UpdateDateOriginal “, que é o formato padrão de datas do WCF, e meu ” UpdateDate “, que é formatado para algo mais legível.

insira a descrição da imagem aqui

Veja como fazer isso:

Alterando o formato de data do WCF

Espero que isto ajude.

O mais fácil:

var milisegundos = parseInt (data.replace (“/ Date (“, “”) .replace (“) /”, “”));
Var newDate = new Date (milisegundos). toLocaleDateString (“en-UE”);