Pytanie Jak sformatować datę Microsoft JSON?


Biorę moje pierwsze pęknięcie Ajax z jQuery. Dostaję moje dane na moją stronę, ale mam problem z danymi JSON, które są zwracane dla typów danych Date. Zasadniczo otrzymuję ciąg znaków, który wygląda następująco:

/Date(1224043200000)/

Od kogoś zupełnie nowego do JSON - jak mam to sformatować w krótkim formacie daty? Czy należy to zrobić gdzieś w kodzie jQuery? Próbowałem jQuery.UI.datepicker wtyczka za pomocą $.datepicker.formatDate() bez powodzenia.

FYI: Oto rozwiązanie, które wymyśliłem, używając kombinacji odpowiedzi tutaj:

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

To rozwiązanie dostało mój obiekt z metody wywołania zwrotnego i poprawnie wyświetli daty na stronie przy użyciu biblioteki formatu daty.


1793


pochodzenie


To może być interesujące: hanselman.com/blog/... - citronas
Format /Date(...)/ jest specyficzny dla wbudowanego formatu daty JSON firmy Microsoft - nie jest częścią żadnego standardu, a JSON, pochodzący z Javascript, ma standard: Format ISO Javascript określa: stackoverflow.com/a/15952652/176877  Pytanie to dotyczy formatu Microsoft JSON Date. Zmodyfikowałem tytuł, aby to wyjaśnić. - Chris Moschini
Żartujesz! Microsoft stworzył własny spin na JSON! i na daty !! Kiedy się nauczą! - Nick.McDermaid
Użyj Newtonsoft JSON po stronie .NET i ładnie wpisane wartości po stronie JS, po prostu użyj: github.com/RickStrahl/json.date-extensions - baHI


Odpowiedzi:


Eval nie jest konieczne. To zadziała dobrze:

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

Funkcja substr pobiera część "/ Date (", a funkcja parseInt pobiera liczbę całkowitą i ignoruje ") /" na końcu. Wynikowa liczba jest przekazywana do konstruktora Date.

EDYCJA: Celowo pominięto radix (drugi argument do parseInt); widzieć mój komentarz poniżej. Ponadto całkowicie się z tym zgadzam Komentarz Rory'ego: Daty ISO-8601 są preferowane w porównaniu z tym starym formatem - więc ten format zazwyczaj nie powinien być używany do nowego rozwoju. Zobacz doskonałe Json.NET biblioteka to świetna alternatywa, która serializuje daty w formacie ISO-8601.

W przypadku dat JSON sformatowanych w ISO-8601 wystarczy przekazać ciąg do konstruktora Date:

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

1566



@Broam: Obie metody (funkcja wymiany i ta odpowiedź) musiałyby ulec zmianie, gdyby MS zmieniło format. - Roy Tinker
@LeeWhitney: Tak, ale zignoruje sufiks (który jest przesunięciem strefy czasowej). Funkcja parseInt pobiera cyfry z przedniej części łańcucha przekazanego do niego, aż napotka nieznakowy znak lub koniec łańcucha, w którym to momencie przestaje i zwraca wynik liczbowy. - Roy Tinker
Czy mógłbyś zaktualizować go datą radix var = new Date (parseInt (jsonDate.substr (6), 10)); - James Kyburz
@JamesKyburz: każda reguła ma wyjątki i myślę, że jest tak, gdy ma zastosowanie wyjątek. Numery dat JSON z .NET nigdy mieć wiodącą "0", więc możemy bezpiecznie opuścić planszę. - Roy Tinker
Warto zauważyć, że ten format daty jest dość zły, a ogólny ruch dotyczy dat sformatowanych w ISO-8601 w JSON. Widzieć hanselman.com/blog/... - Rory


Możesz użyć tego, aby uzyskać datę z JSON:

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

A potem możesz użyć Format daty JavaScript skrypt (1.2 KB, gdy minified i gzipped), aby wyświetlić go, jak chcesz.


115



Nie ma nic złego w linii, kolejność jest \ //. Pierwszy slash ucieka, więc nie liczy się jak komentarz. To twój edytor cię oszukuje, linia zadziała dobrze. - andreialecu
@Rball, nonsens: jsonDate = new Date(+jsonDate.replace(/\/Date\((\d+)\)\//, '$1')); - eyelidlessness
pst było poprawne, można to zrobić na wiele sposobów bez "eval". Crockford mówi, że "eval Is Evil", ponieważ jest mniej czytelny i mniej bezpieczny, ponadto może dalej sugerować, że jest mniej wydajny i bardziej niebezpieczny, ponieważ uderza w kompilator javascript. - Mark Rogers
@Edy: new Function jest prawie tak źle, jak eval: dev.opera.com/articles/view/efficient-javascript/... - Marcel Korpel
@Edy: To jest inna forma ewaluacji i jest równie "zła". Zamiast tego przeanalizuj ciąg znaków (zobacz moją odpowiedź poniżej) - Roy Tinker


Dla osób korzystających z Newtonsoft Json.NET, przeczytaj, jak to zrobić Natywny JSON w IE8, Firefox 3.5 plus Json.NET.

Pomocna jest również dokumentacja dotycząca zmiany formatu dat napisanych przez Json.NET: Serializing Dates with Json.NET

Dla tych, którzy są zbyt leniwi, oto szybkie kroki. Ponieważ JSON ma luźną implementację DateTime, musisz użyć IsoDateTimeConverter(). Zauważ, że od Json.NET 4.5 domyślnym formatem daty jest ISO, więc poniższy kod nie jest potrzebny.

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

JSON przejdzie jako

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

Wreszcie, trochę JavaScript, aby przekonwertować datę ISO na datę 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;
}

Użyłem tego w ten sposób

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

84



Konstruktor daty JavaScript może przeanalizować ciąg znaków dla ciebie: new Date("2009-04-12T20:44:55") - David Hogue
Ostrzeżenie - Formaty i parsowanie konstruktora Date () przed standardem ECMAScript 6. są niestandardowe. Na przykład IE 9 traktuje datę, kiedy konstruktor nadaje czas lokalny, nawet jeśli jest w IS0-8601, co jest implikowane jako UCT wszędzie indziej. Nie polegaj na konstruktorze daty, jeśli obsługujesz starsze przeglądarki. codeofmatt.com/2013/06/07/... - DanO
Przesłanie daty innej niż data UTC prędzej czy później spowoduje kłopoty. - tymtam


Oryginalny przykład:

/Date(1224043200000)/  

nie odzwierciedla formatowania używanego przez WCF podczas wysyłania dat za pośrednictwem WCF REST przy użyciu wbudowanej serializacji JSON. (przynajmniej na .NET 3.5, SP1)

Uważam, że odpowiedź tutaj jest pomocna, ale wymagana jest niewielka edycja do wyrażenia regularnego, ponieważ wydaje się, że przesunięcie czasowe GMT jest dołączane do liczby zwróconej (od 1970) w WCF JSON.

W usłudze WCF mam:

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

ApptVisitLinkInfo definiuje się po prostu:

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

Kiedy "Field2" jest zwracane jako Json z usługi, wartość jest następująca:

/Date(1224043200000-0600)/

Zwróć uwagę na przesunięcie strefy czasowej zawarte jako część wartości.

Zmodyfikowane wyrażenie regularne:

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

Jest nieco bardziej chętny i chwyta wszystko pomiędzy parens, a nie tylko pierwszy numer. Wynikowy czas sinze 1970, a także przesunięcie strefy czasowej mogą zostać wprowadzone do eval, aby uzyskać obiekt daty.

Wynikowa linia JavaScript do zastąpienia to:

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

57



to jest złe, nowa data (1224043200000-0600) odejmuje tylko 600 od daty, w tym przypadku 600 milisekund, a nie 6 godzin, jak powinno. - ariel
@ariel: Spójrz na JavaScript Data od milisekund i strefa czasowa - Bergi
Myślę, że przesunięcie strefy czasowej jest uwzględnione tylko wtedy, gdy masz strefę czasową w obiekcie DateTime w .NET (co jest domyślnym zachowaniem). Jeśli twoja data jest w UTC, użyj DateTime.SpecifyKind (date, DateTimeKind.UTC), a otrzymasz prawidłową wartość UTC, gdy serializuje się, bez przesunięcia, które możesz następnie przekonwertować z powrotem do strefy czasowej użytkownika w razie potrzeby. Jeśli jest to czas lokalny, użyj funkcji .ToUniversalTime (), a zostanie ona przekształcona w UTC i zostanie już określony rodzaj "Rodzaju". - jvenema
w javascript-0100 będzie ciągiem binarnym, więc bądź ostrożny! - verbedr
kiedy masz już konwertowaną z WCF na JS datę, odwróć. Musisz daty jako liczba całkowita (przy użyciu date.getTime ()), które chcesz przekazać do tego samego WCF? - NitinSingh


Nie powtarzaj się - zautomatyzuj konwersję daty za pomocą $.parseJSON()

Odpowiedzi na twój post zapewniają ręczną konwersję daty na daty JavaScript. Rozszerzyłem jQuery $.parseJSON() tylko trochę, dzięki czemu jest w stanie automatycznie parsować daty, kiedy tego poinstruujesz. Przetwarza daty w formacie ASP.NET (/Date(12348721342)/), jak również daty w formacie ISO (2010-01-01T12.34.56.789Z), które są obsługiwane przez natywne funkcje JSON w przeglądarkach (i bibliotekach takich jak json2.js).

Tak czy inaczej. Jeśli nie chcesz wielokrotnie powtarzać kodu konwersji, sugeruję przeczytanie ten wpis na blogu i zdobądź kod, który ułatwi ci życie.


53





Jeśli powiesz w JavaScript,

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

zobaczysz, że jest to poprawna data i możesz użyć tego w dowolnym miejscu kodu JavaScript z dowolną strukturą.


50



Tak też bym pomyślał, gdyby nie koniec: var thedate = / Date (1224043200000) /; przynajmniej dla mnie... - rball
Data () i Data (1224043200000) dają taki sam wynik zarówno w przeglądarce Chrome, jak i Firefox. Nie wiem, czy działało to w starych przeglądarkach, ale ta odpowiedź nie działa teraz w przeglądarkach. - James
@James, Tak, podaje aktualną datę przeglądarki. :( - vissu
Musisz napisać to jako "nowa data (1224043200000)". - BrainSlugs83


Kliknij tutaj, aby sprawdzić wersję demonstracyjną

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

Wynik - "10/15/2008"


47



Po prostu ulepszenie dla powyższej metody. function formatearFecha (fec) {var value = new Data (parseInt (fec.replace (/ (^. * () | ([+ -]. * $) / g, ''))); var mes = value.getMonth (); var dia = value.getDate (); var date = dia + "/" + mes + "/" + value.getFullYear (); if (dia <10) date = date.substr (0, 0) + '0' + dia + date.substr (1), jeśli (mes <10) date = date.substr (0, 3) + '0' + mes + date.substr (4), data powrotu;} data sformatowana do ddMMyyyy. Pozdrawiam! - Matias
ohh !!! Dziękuję bardzo!!! to naprawdę sprawiło, że mój miesiąc. - Raihan Ridoy


Zaktualizowano

Mamy wewnętrzną bibliotekę UI, która musi poradzić sobie zarówno z wbudowanym w Microsoft programem ASP.NET w formacie JSON, jak /Date(msecs)/, zapytał o to oryginalnie, i większość formatu daty JSON, w tym JSON.NET, jak 2014-06-22T00:00:00.0. Ponadto musimy sobie z tym poradzić niezdolność oldIE do radzenia sobie z niczym oprócz 3 miejsc dziesiętnych.

Najpierw sprawdzamy, jakiego rodzaju danych używamy, i parsujemy go w normalny JavaScript Date obiekt, a następnie sformatuj go.

1) Wykryj format daty Microsoft

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

2) Wykryj format daty 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) Format daty MS:

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

4) Przetwórz format daty ISO.

Mamy przynajmniej możliwość upewnienia się, że mamy do czynienia ze standardowymi datami ISO lub datami ISO zmodyfikowanymi tak, aby zawsze mieć trzy milisekundy miejsc (patrz wyżej), więc kod różni się w zależności od środowiska.

4a) Przetwarzaj standardowy format daty ISO, radzenia sobie z problemami 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) Przetwarzaj format ISO z ustalonymi miejscami dziesiętnymi z dokładnością do 3 milisekund - o wiele łatwiej:

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

5) Formatuj:

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) Połącz to wszystko razem:

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

    return formatDate(d);
}

Poniższa stara odpowiedź jest przydatna do powiązania tego formatowania daty z analizą JSU w jQuery, aby uzyskać obiekty Date zamiast ciągów lub jeśli w jakiś sposób utknąłeś w jQuery <1.5.

Stara odpowiedź

Jeśli korzystasz z funkcji Ajax jQuery 1.4 z ASP.NET MVC, możesz przekształcić wszystkie właściwości DateTime w obiekty Date za pomocą:

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

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

W jQuery 1.5 można uniknąć przesłonięcia parseJSON metoda globalnie za pomocą opcji konwerterów w wywołaniu Ajax.

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

Niestety musisz przełączyć się na starszą ścieżkę eval, aby Date przeanalizowało globalnie na miejscu - w przeciwnym razie musisz przekonwertować je na podstawie kolejnych przypadków post-parsowania.


31





Musiałem również znaleźć rozwiązanie tego problemu i ostatecznie natknąłem się na moment.js, który jest ładną biblioteką, która może analizować ten format daty i wiele innych.

var d = moment(yourdatestring)

Oszczędziło mi to trochę bólu głowy, więc pomyślałem, że podzielę się nim z tobą. :)
Tutaj znajdziesz więcej informacji na ten temat: http://momentjs.com/


21