Wie analysiere ich JSON, um ein Date-Objekt in JavaScript zu erhalten?

117

Ich habe ein folgendes Stück JSON:

\/Date(1293034567877)\/

Welches ist ein Ergebnis dieses .NET-Codes:

var obj = DateTime.Now;
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
serializer.Serialize(obj).Dump();

Das Problem, mit dem ich jetzt konfrontiert bin, ist, wie man daraus ein Datumsobjekt in JavaScript erstellt. Alles, was ich finden konnte, war eine unglaubliche Regex-Lösung (viele enthielten Fehler).

Es ist kaum zu glauben, dass es keine elegante Lösung gibt, da dies alles in JavaScrip ist. Ich meine JavaScript-Code, der versucht, JSON (JavaScript Object Notation) zu lesen, das ein JavaScript-Code sein soll, und im Moment stellt sich heraus, dass dies nicht der Fall ist, weil JavaScript dies nicht kann mach hier einen guten Job.

Ich habe auch einige Bewertungslösungen gesehen, die ich nicht zum Laufen bringen konnte (abgesehen davon, dass sie als Sicherheitsbedrohung bezeichnet wurden).

Gibt es wirklich keine Möglichkeit, dies auf elegante Weise zu tun?

Ähnliche Frage ohne echte Antwort:
So analysieren Sie das ASP.NET JSON-Datumsformat mit GWT

Piotr Owsiak
quelle
2
Sie können den Zeitstempel einfach an den Client übergeben und ihn aufrufen new Date().
jAndy
Wenn ich einen Zeitstempel hätte, könnte ich, aber ich habe JSON, das JavaScript anscheinend nicht versteht [sic!]
Piotr Owsiak

Antworten:

51

Es gibt keine Standard-JSON-Darstellung von Datumsangaben. Sie sollten das tun, was @jAndy vorgeschlagen hat, und a überhaupt nicht serialisieren DateTime. Senden Sie einfach eine RFC 1123-Datumszeichenfolge ToString("r")oder eine Nummer aus der Unix-Epoche oder etwas anderes, das Sie im JavaScript zum Erstellen einer verwenden können Date.

Jacob
quelle
3
Vielen Dank, dass ich einen toten Weg gegangen bin. Sie haben als erste darauf hingewiesen, dass JSON den Datumstyp nicht unterstützt.
Piotr Owsiak
3
JSON unterstützt Zahlen, Zeichenfolgen, Objekte, Arrays und die Literale true, false und null. Da Datum keines davon ist, handelt es sich um einen komplexen Typ, der als Objekt und nicht als Zeichenfolge gespeichert werden sollte. Sie können also Typinformationen wie den Typnamen in spezielle Elemente wie "$ type" aufnehmen, die sich niemals in a auflösen würden echtes Objektmitglied. Solche Metamitglieder können verwendet werden, um das JSON-Objekt später zu einem stark typisierten Laufzeitobjekt wiederzubeleben. Ich denke, die Praxis, ein Datum in eine Zeichenfolge zu stecken, ist dumm, weil es unnötigerweise reservierte Zeichenfolgenmuster erstellt und versucht, sie auf jeder Zeichenfolge abzugleichen.
Triynko
4
Es gibt jetzt ein Standard-JSON-Datumsformat. tools.ietf.org/html/rfc7493#section-4.3
Bryan Larsen
128

Die JSON.parseFunktion akzeptiert eine optionale DateTime-Reviver-Funktion. Sie können eine Funktion wie diese verwenden:

dateTimeReviver = function (key, value) {
    var a;
    if (typeof value === 'string') {
        a = /\/Date\((\d*)\)\//.exec(value);
        if (a) {
            return new Date(+a[1]);
        }
    }
    return value;
}

Dann ruf an

JSON.parse(somejsonstring, dateTimeReviver);

Und deine Daten werden richtig herauskommen.

Tim
quelle
1
Gut entdeckt, sehr nützlich.
Gruppe
5
Diese Praxis, nicht primitiv typisierte Daten in einem primitiven Typ (String) zu codieren, ist verrückt. Codieren Sie Datumsangaben in einem JSON-Objekt mit aussagekräftigen Eigenschaften oder fügen Sie noch eine "$ type" -Eigenschaft in das JSON-Objekt ein, damit die Routine zum Analysieren / Deserialisieren den Typ entsprechend wiederbeleben und sogar benutzerdefinierte Konverter verwenden kann, wenn Sie alle packen möchten die Informationen in einen einzelnen Eigenschaftswert wie "Ticks" oder "ms_since_epoch".
Triynko
7
Ich musste den regulären Ausdruck wie folgt ändern: / \ / Date ((-? \ D *)) \ //, damit er auch negative Zahlen verarbeiten kann. Negative Zahlen werden angezeigt, wenn Sie eine sehr alte DateTime (vor der Epoche) haben, die von .NET in JSON konvertiert wurde.
ClearCloud8
@ ClearCloud8: Sie vermissen Schrägstriche: / \ / Date \ ((-? \ D *) \) \ //
Jerther
1
Ich wusste nie über diese Funktion Bescheid - das ist so nützlich!
Keldar
50

Diese Antwort von Roy Tinker hier :

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

Wie er sagt: Die substr-Funktion entfernt den Teil "/ Date (", und die parseInt-Funktion erhält die Ganzzahl und ignoriert das ") /" am Ende. Die resultierende Nummer wird an den Date-Konstruktor übergeben.

Eine andere Möglichkeit besteht darin, Ihre Informationen auf der ASP-Seite einfach richtig zu formatieren, damit JavaScript sie leicht lesen kann. Betrachten Sie dies für Ihre Daten:

DateTime.Now()

Welches sollte ein Format wie dieses zurückgeben:

7/22/2008 12:11:04 PM

Wenn Sie dies an einen JavaScript- DateKonstruktor wie folgt übergeben:

var date = new Date('7/22/2008 12:11:04 PM');

Die Variable enthält datejetzt diesen Wert:

Tue Jul 22 2008 12:11:04 GMT-0700 (Pacific Daylight Time)

Natürlich können Sie dieses DateTimeObjekt in jede Art von Zeichenfolge / int formatieren, die der JS- DateKonstruktor akzeptiert.

Baumgesicht
quelle
Danke Baumgesicht, diese Antwort hat mir kürzlich bei etwas geholfen!
Malice
4
Verlassen Sie sich niemals auf Standardformate für die Konvertierung von Datums- <-> Zeichenfolgen. Die Verwendung von Millisekunden seit Epoche, die im Bereich der numerischen Typen verbleibt, ist weitaus einfacher und zuverlässiger.
Johan Boulé
2
Diese Antwort bietet zwei Lösungen - die erste ist richtig (die parseInt) und die zweite falsch, also nicht sicher, ob Sie upvoten oder downvoten sollen! Das Problem bei der einfachen Ausgabe als Zeichenfolge besteht darin, dass das Datum leicht rückwärts gedreht werden kann, wenn sich der Server in einem Land befindet, z. B. in den USA, und der Browser in einem anderen, z. B. in Großbritannien.
Mike Nelson
Die erste Antwort, um mir einen Hinweis zu geben
Nick.McDermaid
Eine OK-Antwort bis " Erwägen Sie, dies für Ihre Daten zu tun ... ". Es ist keine gute Idee, ein nicht standardmäßiges Format vorzuschlagen, das implementierungsabhängige Analyse- und Zeitzonenprobleme einführt. Das OP-Format ist vorzuziehen (wenn auch nicht ideal).
RobG
21

Wenn Sie das ISO8601-Datum im JavaScript-Stil in JSON verwenden, können Sie dieses von MDN aus verwenden

var jsonDate = (new Date()).toJSON();
var backToDate = new Date(jsonDate);
console.log(jsonDate); //2015-10-26T07:46:36.611Z
LeeGee
quelle
2
Imo ist dies die eleganteste Antwort und sollte die akzeptierte sein.
John
1
Sehr elegant, aber dies bezieht sich nicht auf das spezifische Datumsformat, das in der Frage erwähnt wurde.
Asien
@aslop - Wenn der Benutzer ein Datum nicht in / von ISO konvertieren kann, ist JSON das geringste Problem.
LeeGee
7

Sie können das JSON-Datum in JavaScript in das normale Datumsformat konvertieren.

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

Was ist falsch mit:

new Date(1293034567877);

Dies kehrt für mich zurück "Wed Dec 22 2010 16:16:07 GMT + 0000 (GMT Standard Time)".

Oder müssen Sie die Nummer aus dem JSON herausholen?

Psytronic
quelle
3
Was ist falsch an Ihrer Lösung? Nun, der 1293034567877 ist nicht der JSON, den ich habe, oder? Außerdem muss ich die Nummer nicht aus dem JSON herausholen, ich muss das Datum aus dem JSON herausholen. Ich erwarte ein bisschen mehr von JavaScript, als nur alles mit Regex zu können. Ich brauche meinen Code, um lesbar zu sein und nicht wie ein Cartoon-Fluch auszusehen.
Piotr Owsiak
7
Ich würde .NET beschuldigen, eine Serialisierung eines Datumsobjekts in einem so seltsamen Format wie erstellt zu haben \/Date(1293034567877)\/. Wenn es vernünftig wäre, würde es nur die Epochenzeit ausgeben und Sie könnten damit ein Date-Objekt initialisieren.
Quentin
2
@treeface: Wenn JSON kein JavaScript ist, sind meiner Meinung nach Tutorials und Bücher für dieses häufige Missverständnis verantwortlich. Jedenfalls stehe ich wirklich gerne korrigiert da. Was Ihren Vorschlag betrifft, dass Datum als Zeichenfolge dargestellt werden kann, kann ich sagen, dass alles als Zeichenfolge dargestellt werden kann, oder? Aber das würde unsere Arbeit nicht einfacher machen, aber furchtbar schmerzhaft und höllisch. Ich denke, mein Problem rührt von der Tatsache her, dass ich JSON als Serialisierungsformat betrachtete (beworben, um weniger Bandbreite zu beanspruchen und besser mit JavaScript als XML zu arbeiten). Wie sich herausstellt, ist es nicht, zumindest nicht schmerzlos.
Piotr Owsiak
1
@treeface: Ich habe Ihre Behauptung über JSON googelt und herausgefunden, dass JSON JavaScript ist, eigentlich eine Teilmenge von JavaScript. Siehe RFC # 4627 "Die Anwendung / JSON-Medientyp für die JavaScript-Objektnotation (JSON)" und suchen Sie nach einer Aussage: "JSONs Entwurfsziele waren, dass sie minimal, portabel, textuell und eine Teilmenge von JavaScript ist." Wenn ich jetzt darüber nachdenke, scheint es offensichtlich, dass Sie eval () unter JSON aufrufen können.
Piotr Owsiak
1
@ David Dorward: Ich möchte lieber, dass die zusätzliche Komplexität tief in Bibliotheken implementiert wird (entweder .NET, Java, Ruby, Python oder eine beliebige Sprache / Plattform, auf der Sie sich befinden), anstatt die Details dem Programmierer zu überlassen. Beachten Sie auch, dass Sie in JSON keine Unterstützung für boolesche und ganzzahlige Datentypen benötigen. Sie können sie einfach in Zeichenfolgen einfügen, oder? Können Sie sich vorstellen, wie schrecklich es wäre, von JSON irgendetwas zu bekommen?
Piotr Owsiak
2

Ich weiß, dass dies ein sehr alter Thread ist, aber ich möchte dies posten, um denjenigen zu helfen, die wie ich darauf stoßen.

Wenn Sie kein Skript eines Drittanbieters verwenden möchten , können Sie moment, js verwenden. Anschließend können Sie .format () verwenden, um es nach Ihren Wünschen zu formatieren.

Eman
quelle
2

Termine sind immer ein Albtraum. Bei der Beantwortung Ihrer alten Frage ist dies vielleicht der eleganteste Weg:

eval(("new " + "/Date(1455418800000)/").replace(/\//g,""))

Mit eval konvertieren wir unseren String in Javascript-Code. Dann entfernen wir das "/", in die Ersetzungsfunktion ist ein regulärer Ausdruck. Wenn wir mit Neu beginnen, werden unsere Sätze dies ausschließen:

new Date(1455418800000)

Eine Sache, die ich vor langer Zeit verwendet habe, sind lange Werte, die in Ticks dargestellt werden ... warum? Nun, Lokalisierung und denken Sie nicht mehr darüber nach, wie das Datum auf jedem Server oder jedem Client konfiguriert ist. Tatsächlich verwende ich es auch in Datenbanken.

Vielleicht ist diese Antwort ziemlich spät, kann aber jedem helfen, der hier in der Nähe ist.

Gabriel Andrés Brancolini
quelle
Übrigens, mein Englisch mit Jahren wird schlimmer als je zuvor ... aber ich glaube, ich habe mich selbst verstanden.
Gabriel Andrés Brancolini
Ihre Antwort funktioniert großartig, hat mir aus einem Stau geholfen. Vielen Dank.
BoredBsee
1

AngularJS konnte auch keine .NET JSON-Datumszeichenfolge analysieren /Date(xxxxxxxxxxxxx)/.

Ich habe dieses Problem behoben, indem ich das Datum auf die ISO 8601-Zeichenfolgendarstellung formatiert habe, anstatt das DateObjekt direkt zu sichern ...

Hier ist ein Beispiel für ASP.NET MVC-Code.

return Json(new { 
  date : DateTime.Now.ToString("O") //ISO 8601 Angular understands this format
});

Ich habe es versucht, RFC 1123aber es funktioniert nicht. Angular behandelt dies als Zeichenfolge anstelle von Datum.

return Json(new { 
  date : DateTime.Now.ToString("R") //RFC 1123 Angular won't parse this
});
Rosdi Kasim
quelle
0

Ich habe .Net für solche Dinge nicht verwendet. Wenn Sie in der Lage waren, etwas wie das Folgende auszudrucken, sollte es funktionieren.

Hinweis: Sofern Sie diese JSON- Zeichenfolge nicht auf andere Weise analysieren oder nur erwarten, dass Benutzer über moderne Browser mit einem integrierten JSON-Parser verfügen, müssen Sie ein JS-Framework oder JSON2 verwenden, um die vom Server ausgegebene JSON-Zeichenfolge in eine echte JSON-Zeichenfolge zu analysieren Objekt.

// JSON received from server is in string format
var jsonString = '{"date":1251877601000}';

//use JSON2 or some JS library to parse the string
var jsonObject =  JSON.parse( jsonString );

//now you have your date!
alert( new Date(jsonObject.date) );

Wiki Link

Moderne Browser wie Firefox 3.5 und Internet Explorer 8 bieten spezielle Funktionen zum Parsen von JSON. Da die native Browserunterstützung effizienter und sicherer als eval () ist, wird erwartet, dass die native JSON-Unterstützung im nächsten ECMAScript-Standard enthalten sein wird. [6]


Link zur JSON2-Datei

Live-Beispiel

Subhaze
quelle
Ich verstehe, aber mein Problem mit JSON und dem Datumstyp ist, dass ich explizit "neues Datum" (was a) zusätzliche Arbeit b) zusätzliches Wissen ist, das dem Verbraucher mitgeteilt werden muss. Ich bin wirklich enttäuscht, herauszufinden, wie damit umgegangen wird, und halte es grundsätzlich für einen Fehler in der JSON-Spezifikation.
Piotr Owsiak
0

Die Antwort auf diese Frage lautet: Verwenden Sie Nuget, um JSON.NET zu erhalten, und verwenden Sie dies in Ihrer JsonResultMethode:

JsonConvert.SerializeObject(/* JSON OBJECT TO SEND TO VIEW */);

Machen Sie dies aus Ihrer Sicht einfach in javascript:

JSON.parse(/* Converted JSON object */)

Wenn es sich um einen Ajax-Anruf handelt:

var request = $.ajax({ url: "@Url.Action("SomeAjaxAction", "SomeController")", dataType: "json"});
request.done(function (data, result) { var safe = JSON.parse(data); var date = new Date(safe.date); });

Nach dem JSON.parseAufruf können Sie das JSON-Datum in eine new DateInstanz einfügen, da JsonConverteine ordnungsgemäße ISO-Zeitinstanz erstellt wird

Callum Linington
quelle
0
function parseJsonDate(jsonDate) {

    var fullDate = new Date(parseInt(jsonDate.substr(6)));
    var twoDigitMonth = (fullDate.getMonth() + 1) + ""; if (twoDigitMonth.length == 1) twoDigitMonth = "0" + twoDigitMonth;

    var twoDigitDate = fullDate.getDate() + ""; if (twoDigitDate.length == 1) twoDigitDate = "0" + twoDigitDate;
    var currentDate = twoDigitMonth + "/" + twoDigitDate + "/" + fullDate.getFullYear();

    return currentDate;
};
Muzafar
quelle
0

Wie Callum bereits erwähnt hat, ist es für mich am besten, die Controller-Methode in string anstelle von JsonResult zu ändern. "

public string GetValues()
{
  MyObject.DateFrom = DateTime.Now;
  return JsonConvert.SerializeObject(MyObject);
}

Mit der Ajax-Methode können Sie so etwas tun

 $.ajax({
 url: "/MyController/GetValues",
 type: "post",
 success: function (data) {
 var validData = JSON.parse(data);
//if you are using datepicker and you want set a format
$("#DateFrom").val($.datepicker.formatDate("dd/mm/yy", new Date(validData.DateFrom)));                                      
// if you want the date as returned
$("#DateFrom").val(new Date(validData.DateFrom))
}
});
Onixpam
quelle
0

Bei Verwendung der Eval-Funktion muss lediglich der vordere Schrägstrich vorne und hinten entfernt werden.

var date1 = "/Date(25200000)/"
eval("new " + date1.substring(1, date1.length - 1));

ergibt Do 01.01.1970 00:00:00 GMT-0700 (US Mountain Standard Time)

vernmic
quelle
0

Ich bin auf ein Problem mit der externen API gestoßen, die Daten in diesem Format bereitstellt, manchmal sogar mit UTC-Differenzinformationen wie /Date(123232313131+1000)/. Ich konnte das DateObjekt mit folgendem Code drehen

var val = '/Date(123232311-1000)/';
var pattern = /^\/Date\([0-9]+((\+|\-)[0-9]+)?\)\/$/;
var date = null;

// Check that the value matches /Date(123232311-1000)/ format
if (pattern.test(val)) {
  var number = val.replace('/Date(', '',).replace(')/', '');
  if (number.indexOf('+') >= 0) {
    var split = number.split('+');
    number = parseInt(split[0]) + parseInt(split[1]);
  } else if (number.indexOf('-') >= 0) {
    var split = number.split('-');
    number = parseInt(split[0]) - parseInt(split[1]);
  } else {
    number = parseInt(number);
    date = new Date(number);
  }
}
Martin Vich
quelle
-1
//
// formats a .net date into a javascript compatible date
//
function FormatJsonDate(jsonDt) 
{              
    var MIN_DATE = -62135578800000; // const

    var date = new Date(parseInt(jsonDt.substr(6, jsonDt.length-8)));                                                       
    return date.toString() == new Date(MIN_DATE).toString() ? "" : (date.getMonth() + 1) + "\\" + date.getDate() + "\\" + date.getFullYear(); 
}
sunil
quelle
2
Soweit ich den Code verstehe, geben Sie kein Datumsobjekt zurück.
Johan Boulé
-1
function parseJsonDate(jsonDate) {

    var fullDate = new Date(parseInt(jsonDate.substr(6)));
    var twoDigitMonth = (fullDate.getMonth() + 1) + ""; if (twoDigitMonth.length == 1) twoDigitMonth = "0" + twoDigitMonth;

    var twoDigitDate = fullDate.getDate() + ""; if (twoDigitDate.length == 1) twoDigitDate = "0" + twoDigitDate;
    var currentDate = twoDigitMonth + "/" + twoDigitDate + "/" + fullDate.getFullYear();

    return currentDate;
};

// Verwenden Sie diese Funktion

var objDate=parseJsonDate("\/Date(1443812400000)\/");
alert(objDate);
Muzafar Hasan
quelle