„Właściwy” format daty JSON


1137

Widziałem tak wiele różnych standardów formatu daty JSON:

"\"\\/Date(1335205592410)\\/\""         .NET JavaScriptSerializer
"\"\\/Date(1335205592410-0500)\\/\""    .NET DataContractJsonSerializer
"2012-04-23T18:25:43.511Z"              JavaScript built-in JSON object
"2012-04-21T18:25:43-05:00"             ISO 8601

Który jest właściwy? A może najlepiej? Czy jest w tym jakiś standard?


75
W JSON nie ma formatu daty, istnieją tylko ciągi znaków, które de- / serializer decyduje się na mapowanie na wartości dat.

11
strings, numbers, true, false, null, objectsIarrays
Russ Cam

12
Jednak obiekt JSON wbudowany w JavaScript i ISO8601 zawiera wszystkie informacje, które powinien zrozumieć człowiek i komputer i nie opiera się na początku ery komputerowej (1970-1-1).
poussma

Odpowiedzi:


1847

Sam JSON nie określa sposobu reprezentacji dat, ale JavaScript.

Państwo powinno użyć formatu emitowanego przez Date„s toJSONmetody:

2012-04-23T18:25:43.511Z

Dlatego:

  1. Jest czytelny dla człowieka, ale także zwięzły

  2. Sortuje się poprawnie

  3. Zawiera ułamkowe sekundy, które mogą pomóc przywrócić chronologię

  4. Jest zgodny z ISO 8601

  5. ISO 8601 jest znana na całym świecie od ponad dekady

  6. ISO 8601 jest zatwierdzony przez W3C , RFC3339 i XKCD

To powiedziawszy , każda napisana biblioteka dat może zrozumieć „milisekundy od 1970 roku”. Więc dla łatwego przenoszenia, ThiefMaster ma rację.


32
Jest to również preferowane przedstawienie według ECMA :JSON.stringify({'now': new Date()}) "{"now":"2013-10-21T13:28:06.419Z"}"
Steven

11
Dodałbym do listy jeszcze jeden ważny powód: jest niezależny od ustawień regionalnych. Jeśli miałeś datę 02-03-2014, potrzebujesz dodatkowych informacji, aby wiedzieć, czy odnosi się ona do 3 lutego czy 2 marca. Zależy to od tego, czy używany jest format US, czy inny format.
Juanal

107
głosowanie za wspominaniem i łączeniem xkcd: D @ajorquera Zwykle używam do tego momjs. Widziałem również problemy z IE w tym zakresie
fholzer

54
Jeśli chodzi o drugi punkt, nie sortuje się poprawnie po 10000 roku. Mamy jednak prawie 8000 lat na opracowanie nowego formatu, więc prawdopodobnie nie jest to problem.
Erfa

7
W rzeczywistości, @Erfa, ponieważ -pojawia się przed cyframi ASCII, wszystko będzie dobrze, aż do 100 000 roku. ; P
Ben Leggiero

128

JSON nic nie wie o datach. To, co robi .NET, to niestandardowy hack / rozszerzenie.

Użyłbym formatu, który można łatwo przekonwertować na Dateobiekt w JavaScript, tj. Takiego, który można przekazać new Date(...). Najłatwiejszym i prawdopodobnie najbardziej przenośnym formatem jest znacznik czasu zawierający milisekundy od 1970 roku.


3
stackoverflow.com/questions/10286385/… - zobaczmy, czy ktoś wie, dlaczego FF tak się zachowuje.
ThiefMaster

11
Jeśli wybierzesz tę trasę, upewnij się, że nie musisz zajmować się datami wcześniejszymi niż 1970!
Ben Dolman,

8
Jak powiedział @BenDolman, to „rozwiązanie” nie odnosi się odpowiednio do dat sprzed 1 stycznia 1970 r. (Epoka). Jest też powód, dla którego ISO8601 istnieje w pierwszej kolejności. Tutaj na Ziemi mamy rzeczy zwane „strefami czasowymi”. Gdzie to jest w milisekundach? JSON nie może mieć standard datami, ale daty istnieć poza JSON, i nie jest standardem dla tego. odpowiedź funroll jest poprawna (patrz także: xkcd.com/1179 ).
JoeLinux

5
Być może warto również wspomnieć, że (miliony) sekund od 1970 roku nie można przewidzieć dla dat w przyszłości, ponieważ mamy sekundy przestępne . Nie użyłbym tego, gdyby służył do komunikacji między procesami i przechowywania danych. Przyjemnie jest jednak stosować wewnętrznie w programie, ponieważ można go zapisać w jednej liczbie całkowitej, co daje pewne korzyści w zakresie wydajności.
Brodie Garnet

5
Uniksowym znacznikiem czasu jest zawsze UTC, konwertujesz z lokalnej strefy czasowej przed wygenerowaniem znacznika czasu, i wracasz z powrotem do lokalnej strefy czasowej na wyświetlaczu, nie ma tu niejednoznaczności.
lkraider,

46

Nie ma odpowiedniego formatu ; Specyfikacja JSON nie określa formatu wymiany dat, dlatego jest tak wiele różnych sposobów, aby to zrobić.

Najlepszym formatem jest prawdopodobnie data reprezentowana w formacie ISO 8601 ( patrz Wikipedia ); jest to dobrze znany i szeroko stosowany format, który można obsługiwać w wielu różnych językach, dzięki czemu doskonale nadaje się do współpracy. Jeśli na przykład kontrolujesz wygenerowany plik Json, udostępniasz dane innym systemom w formacie json, wybierając 8601 jako format wymiany daty, dobrym wyborem.

Jeśli na przykład nie masz kontroli nad wygenerowanym plikiem Json, jesteś konsumentem oprogramowania Json z kilku różnych istniejących systemów, najlepszym sposobem na to jest skorzystanie z funkcji narzędzia do analizy dat, która obsługuje różne oczekiwane formaty.


2
@mlissner, ale to opinia, która jest najlepsza. ISO-8601 jest standardem, ale nie jest standardem dla JSON (chociaż byłbym skłonny go użyć); na przykład Microsoft zdecydował się go nie używać ( msdn.microsoft.com/en-us/library/… ). Najlepszą praktyką jest trzymanie się jednej (rozsądnej) konwencji, cokolwiek to jest. Jak powiedziałem w odpowiedzi, najlepszym sposobem na to jest zdefiniowanie funkcji narzędzia do analizy dat, która może obsłużyć oczekiwane formaty. Jeśli zintegrujesz z systemami, które używają różnych formatów, funkcja powinna obsłużyć każdą sprawę.
Russ Cam

1
@RussCam możemy poruszać się w tę iz powrotem, ale jeśli ktoś prosi o najlepszy sposób kodowania dat w JSON, pyta, jak sformatować daty podczas tworzenia JSON (i odpowiedź jest na ogół ISO-8601). Odpowiadasz na odwrotne pytanie: jak spożywać daty JSON, gdy już są wykonane (choć twoja rada jest słuszna).
mlissner

1
Specyfikacja schematu JSON faktycznie mówi, że daty weryfikowane przez schemat muszą mieć format 8601.
gnasher729

3
@ gnasher729 czy masz link?
Russ Cam

@vallismortis - jest to specyfikacja robocza do definiowania schematu dla danej struktury JSON wymienianej między stronami, a nie format dat w specyfikacji JSON. Mam zamiar skorygować moją odpowiedź w oparciu o komentarze, nie wydaje się, że wyjaśniłem to wystarczająco
Russ Cam

27

Z RFC 7493 (format wiadomości I-JSON) :

I-JSON oznacza Internet JSON lub Interoperable JSON, w zależności od tego, kogo zapytasz.

Protokoły często zawierają elementy danych zaprojektowane w taki sposób, aby zawierały znaczniki czasu lub czasy trwania. ZALECA się, aby wszystkie takie elementy danych były wyrażone jako wartości łańcuchowe w formacie ISO 8601, jak określono w RFC 3339 , z dodatkowymi ograniczeniami, że należy używać wielkich liter zamiast małych liter, aby strefa czasowa nie była domyślna, oraz że opcjonalne końcowe sekundy być uwzględnione, nawet jeśli ich wartość to „00”. ZALECA się również, aby wszystkie elementy danych zawierające czasy trwania były zgodne z produkcją „czas trwania” w dodatku A do RFC 3339, z tymi samymi dodatkowymi ograniczeniami.


2
Jest to również format tworzony przez Date().toISOString()i Date().toJSON(), z ograniczeniem, które Datenie śledzi wartości strefy czasowej, a zatem zawsze emituje znaczniki czasu w strefie czasowej UTC ( Z). Wartość można przeanalizować za pomocą new Date("...")i Date.parseDate.
Søren Løvborg,

15

Tylko w celach informacyjnych widziałem używany format:

Date.UTC(2017,2,22)

Działa z JSONP, który jest obsługiwany przez $.getJSON()funkcję. Nie jestem pewien, czy posunę się tak daleko, aby zalecić takie podejście ... po prostu wyrzucenie go jako możliwej możliwości, ponieważ ludzie robią to w ten sposób.

FWIW: Nigdy nie używaj sekund od epoki w protokole komunikacyjnym ani milisekund od epoki, ponieważ są one obarczone niebezpieczeństwem dzięki losowej implementacji sekund przestępnych (nie masz pojęcia, czy nadawca i odbiorca poprawnie implementują sekundy przestępne UTC).

Nienawiść do zwierząt domowych, ale wiele osób uważa, że ​​UTC to tylko nowa nazwa GMT - źle! Jeśli twój system nie implementuje sekund przestępnych, oznacza to, że korzystasz z GMT (często nazywany UTC, mimo że jest nieprawidłowy). Jeśli w pełni wykorzystasz sekundy przestępne, naprawdę używasz UTC. Przyszłe sekundy przestępne nie mogą być znane; są one publikowane przez IERS w razie potrzeby i wymagają ciągłych aktualizacji. Jeśli korzystasz z systemu, który próbuje zaimplementować sekundy przestępne, ale zawiera nieaktualną tabelę referencyjną (bardziej powszechną niż mogłoby się wydawać), to nie masz GMT ani UTC, masz dziwny system udający UTC.

Te liczniki daty są kompatybilne tylko wtedy, gdy są wyrażone w formacie z podziałem (y, m, d itp.). NIGDY nie są kompatybilne w formacie epoki. Miej to w pamięci.


4
Nie użyłbym tego formatu, ale reszta podanych przez ciebie informacji jest bardzo przydatna, dziękuję!
Robert Mikes,

9

W razie wątpliwości wystarczy przejść do konsoli internetowej javascript nowoczesnej przeglądarki, naciskając klawisz F12 (Ctrl + K w przeglądarce Firefox) i napisz:

new Date().toISOString()

Wyjdzie:

„2019-07-04T13: 33: 03.969Z”

Ta-da !!


3

Uważam, że najlepszym formatem dla uniwersalnej interoperacyjności nie jest ciąg ISO-8601, ale format używany przez EJSON:

{ "myDateField": { "$date" : <ms-since-epoch> } }

Jak opisano tutaj: https://docs.meteor.com/api/ejson.html

Korzyści

  1. Analiza wydajności: Jeśli przechowujesz daty jako ciągi znaków ISO-8601, jest to świetne, jeśli oczekujesz wartości daty w tym konkretnym polu, ale jeśli masz system, który musi określać typy wartości bez kontekstu, analizujesz każdy ciąg znaków dla format daty.
  2. Nie ma potrzeby sprawdzania poprawności daty: Nie musisz się martwić o sprawdzanie poprawności i weryfikacji daty. Nawet jeśli łańcuch pasuje do formatu ISO-8601, może nie być prawdziwą datą; tak się nigdy nie stanie z datą EJSON.
  3. Jednoznaczna deklaracja typu: jeśli chodzi o ogólne systemy danych, jeśli chcesz przechowywać ciąg ISO jako ciąg w jednym przypadku, a rzeczywista data systemowa w innym, ogólne systemy przyjmujące format ciągu ISO-8601 nie pozwolą na to, mechanicznie (bez sztuczek ucieczki lub podobnych okropnych rozwiązań).

Wniosek

Rozumiem, że format czytelny dla człowieka (ciąg ISO-8601) jest pomocny i wygodniejszy w 80% przypadków użycia, i w rzeczywistości nikt nie powinien być informowany, aby nie przechowywał swoich dat jako ciągów ISO-8601, jeśli takie są ich aplikacje rozumiemy, ale dla powszechnie przyjętego formatu transportu, który powinien gwarantować pewne wartości, na pewno daty, w jaki sposób możemy pozwolić na dwuznaczność i potrzebę tak dużej walidacji?


Zobacz tę odpowiedź wcześniej w wątku, dlaczego milisekundy od epoki zawierają zastrzeżenia, takie jak niepoprawne obliczenie sekund przestępnych itp: stackoverflow.com/a/42480073/190476
Sudhanshu Mishra

@SudhanshuMishra Zastrzeżenia, o których wspominasz, to ogólne poglądy na bardzo akademickie obawy dotyczące uniksowych znaczników czasu, głównie związanych z generowaniem znaczników czasu. Jest to tym bardziej niepokojące w przypadku rozdzielczości milisekundowej. Jak wspomniano w innym komentarzu, większość dat komputerowych jest wewnętrznie reprezentowana jako uniksowe znaczniki czasu, nawet jeśli są one ujawnione i sformatowane w inny sposób. Niemniej jednak nie ma nic złego w milisekundowej reprezentacji dowolnej daty + godziny, szczególnie w porównaniu z innymi podejściami, na które z łatwością mogą wpływać te same ostrzeżenia o uderzeniu w nanotechnologię pod maską.
Ciabaros

Wystarczy dodać, że dotyczą dat „poza zakresem” znaczników czasu unix: są to problemy z pamięcią systemową, które należy rozwiązać w znacznie szerszym kontekście niż format transportu. Na przykład ten format nie musi być ograniczony do liczb całkowitych pasujących do 32 bitów, ani nie musi być liczbami ściśle dodatnimi, ale nikt nie zamierza rozwiązać problemu „roku 2038” poprzez upuszczenie znaczników czasu na poziomie systemu / architektury ; po prostu trzeba je rozszerzyć (np. do wersji 64-bitowej lub nowszej), co nie wpływa na proponowany format transportu.
Ciabaros,

3

Sam JSON nie ma formatu daty, nie obchodzi go, jak ktokolwiek przechowuje daty. Ponieważ jednak pytanie to jest oznaczone javascript, zakładam, że chcesz wiedzieć, jak przechowywać daty javascript w JSON. Możesz po prostu podać datę do JSON.stringifymetody, a ona użyje Date.prototype.toJSONdomyślnie, która z kolei używa Date.prototype.toISOString( MDN na Date.toJSON ):

const json = JSON.stringify(new Date());
const parsed = JSON.parse(json); //2015-10-26T07:46:36.611Z
const date = new Date(parsed); // Back to date object

Uznałem również, że użyteczne jest użycie reviverparametru JSON.parse( MDN na JSON.parse ) do automatycznej konwersji ciągów ISO z powrotem na daty javascript za każdym razem, gdy czytam ciągi JSON.

const isoDatePattern = new RegExp(/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/);

const obj = {
 a: 'foo',
 b: new Date(1500000000000) // Fri Jul 14 2017, etc...
}
const json = JSON.stringify(obj);

// Convert back, use reviver function:
const parsed = JSON.parse(json, (key, value) => {
    if (typeof value === 'string' &&  value.match(isoDatePattern)){
        return new Date(value); // isostring, so cast to js date
    }
    return value; // leave any other value as-is
});
console.log(parsed.b); // // Fri Jul 14 2017, etc...

2

Preferowanym sposobem jest użycie 2018-04-23T18:25:43.511Z...

Poniższy obrazek pokazuje, dlaczego jest to preferowany sposób:

Data JSON

Jak widać, Date ma natywną metodę toJSON, którą returnw tym formacie można łatwo przekonwertować na Datejeszcze raz ...


2
Poprawny! Składnia wymiany danych JSON nie określa standardu: ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf, ale w praktyce formaty zgodne z ISO 8601 są bardziej pożądane na różnych platformach, w tym w środowisku wykonawczym JavaScript.
Kamyar Nazeri

1

W Sharepoint 2013, pobieranie danych w JSON nie ma formatu do konwersji daty na format tylko daty, ponieważ w tej dacie powinien być format ISO

yourDate.substring(0,10)

To może ci pomóc


0

„2014-01-01T23: 28: 56.782Z”

Data jest reprezentowana w standardowym i sortowalnym formacie, który reprezentuje czas UTC (wskazany przez Z). ISO 8601 obsługuje również strefy czasowe, zastępując Z wartością + lub - dla przesunięcia strefy czasowej:

„2014-02-01T09: 28: 56.321-10: 00”

Istnieją inne odmiany kodowania strefy czasowej w specyfikacji ISO 8601, ale format –10: 00 jest jedynym formatem TZ obsługiwanym przez obecne parsery JSON. Ogólnie najlepiej jest używać formatu opartego na UTC (Z), chyba że istnieje konkretna potrzeba ustalenia strefy czasowej, w której data została utworzona (możliwe tylko w przypadku generowania po stronie serwera).

NB: var date = new Date (); console.log (data); // śr. 01.01.2014 13:28:56 GMT- 1000 (hawajski czas standardowy)

var json = JSON.stringify(date);
console.log(json);  // "2014-01-01T23:28:56.782Z"

aby powiedzieć, że jest to preferowany sposób, mimo że JavaScript nie ma standardowego formatu

// JSON encoded date
var json = "\"2014-01-01T23:28:56.782Z\"";

var dateStr = JSON.parse(json);  
console.log(dateStr); // 2014-01-01T23:28:56.782Z

0

Jeśli używasz Kotlin, to rozwiąże twój problem. (Format MS Json)

val dataString = "/Date(1586583441106)/"
val date = Date(Long.parseLong(dataString.substring(6, dataString.length - 2)))

-3

działa dla mnie z parsowaniem serwera

{
    "ContractID": "203-17-DC0101-00003-10011",
    "Supplier":"Sample Co., Ltd",
    "Value":12345.80,
    "Curency":"USD",
    "StartDate": {
                "__type": "Date",
                "iso": "2017-08-22T06:11:00.000Z"
            }
}

-6

Jest tylko jedna poprawna odpowiedź na to pytanie i większość systemów źle ją rozumie. Liczba milisekund od epoki, czyli 64-bitowa liczba całkowita. Strefa czasowa jest problemem związanym z interfejsem użytkownika i nie ma działalności w warstwie aplikacji lub db. Dlaczego db ma dbałość o strefę czasową, skoro wiesz, że zapisze ją jako 64-bitową liczbę całkowitą, wykonaj obliczenia transformacji.

Usuń niepotrzebne fragmenty i traktuj daty jak liczby aż do interfejsu użytkownika. Za pomocą prostych operatorów arytmetycznych można wykonywać zapytania i logikę.


Komentarze zostały przeniesione do czatu .
Jon Clements

5
Teraz masz 2 problemy: Którą epokę wybrać i jakie milisekundy policzyć? Prawdopodobnie najczęstszym wyborem jest czas uniksowy (1970-01-01T00: 00: 00 milisekund UTC i SI, z wyjątkiem tych, które przypadają w ułamku sekundy), ale oczywiście sprawia, że ​​przyszłe czasy nie są zdefiniowane.
aij

2
Jak zatem reprezentujesz mikrosekundy? RFC3339 działa dobrze z dowolną precyzją, będziesz miał czytnik, który analizuje strefę czasową i daje odpowiedni znacznik czasu oraz dodatkowe informacje. Aplikacje kalendarza zwykle dbają o strefy czasowe.
gnasher729,

11
Strefa czasowa nie dotyczy interfejsu użytkownika, chyba że nie masz nic przeciwko pominięciu następnego lotu. Loty są publikowane w czasie lokalnym i podlegają określonym zasadom dotyczącym zmian czasu letniego. Utrata offsetu oznacza utratę ważnych informacji biznesowych
Panagiotis Kanavos,

1
Niektóre inne kontrargumenty obejmują zdolność do przedstawiania czasów sprzed 1970 roku (zakładając, że ta konkretna epoka) oraz tendencję JSON do czytelności dla człowieka.
Timo

-8

Poniższy kod działał dla mnie. Ten kod wydrukuje datę w formacie DD-MM-RRRR .

DateValue=DateValue.substring(6,8)+"-"+DateValue.substring(4,6)+"-"+DateValue.substring(0,4);

w przeciwnym razie możesz również użyć:

DateValue=DateValue.substring(0,4)+"-"+DateValue.substring(4,6)+"-"+DateValue.substring(6,8);

-19

Myślę, że to naprawdę zależy od przypadku użycia. W wielu przypadkach korzystniejsze może być użycie odpowiedniego modelu obiektowego (zamiast renderowania daty w ciągu), na przykład:

{
"person" :
      {
 "name" : {
   "first": "Tom",
   "middle": "M",
  ...
}
 "dob" :  {
         "year": 2012,
         "month": 4,
         "day": 23,
         "hour": 18,
         "minute": 25,
         "second": 43,
         "timeZone": "America/New_York"
    }   
   }
}

Wprawdzie jest to bardziej szczegółowe niż RFC 3339, ale:

  • jest również czytelny dla człowieka
  • implementuje odpowiedni model obiektowy (jak w OOP, o ile pozwala na to JSON)
  • obsługuje strefy czasowe (nie tylko przesunięcie UTC w danym dniu i godzinie)
  • może obsługiwać mniejsze jednostki, takie jak milisekundy, nanosekundy ... lub po prostu ułamkowe sekundy
  • nie wymaga osobnego kroku analizy (aby przeanalizować ciąg daty i godziny), parser JSON zrobi wszystko za Ciebie
  • łatwe tworzenie przy użyciu dowolnej ramy czasowej lub implementacji w dowolnym języku
  • można łatwo rozszerzyć o obsługę innych skal kalendarza (hebrajski, chiński, islamski ...) i epok (AD, BC, ...)
  • jest bezpieczny rok 10000 ;-) (RFC 3339 nie jest)
  • obsługuje daty całodniowe i zmienne czasy (JavaScript Date.toJSON()nie)

Nie sądzę, aby poprawne sortowanie (jak zauważył funroll dla RFC 3339) jest funkcją, która jest naprawdę potrzebna podczas szeregowania randki w JSON. Dotyczy to także dat i godzin mających takie same przesunięcie strefy czasowej.


7
Wątpię, czy ktokolwiek będzie używał Jsona w roku 10000, a nawet że do tego czasu rok 10000 będzie nadal rokiem 10000. Ale jeśli obie te rzeczy będą nadal prawdziwe, format można po prostu rozszerzyć, aby zawierał 3 cyfry składnik wieku. Powiedziałbym więc, że ludzie mogą bezpiecznie trzymać się RFC 3339, przynajmniej do roku 9900
wspomnienie snu z

8
@downvoters: Według Dlaczego głosowanie jest ważne? należy downvote jeśli post contains wrong information, is poorly researched, or fails to communicate information. Wyjaśnij, z którego z tych powodów odmówiłeś swojej odpowiedzi.
Marten

5
@Marten Dwie rzeczy. 1. Nigdy nie należy się ci wyjaśnienie pochlebnych opinii, choć rozumiem, że może to być pomocne. 2. Nie głosowałem za twoją odpowiedzią, ale zgaduję, że ludzie nie lubią twojej odpowiedzi, ponieważ uważają, że jest to niewłaściwy sposób. To kwalifikuje się jako „błędna informacja”, ponieważ pytanie szuka najlepszego sposobu na zrobienie czegoś
Kevin Wells,

7
Nie głosowałem za tobą, ale z pewnością rozumiem, w jaki sposób „wynaleźć jeszcze jeden źle określony format” (który w zasadzie mówisz) byłby postrzegany jako zły lub źle zbadany.
aij

2
@Phil, UTC tak naprawdę nie jest strefą czasową (nie ma miejsca na ziemi, która używa „UTC” jako oficjalnej strefy czasowej), jest to standard czasu . Przesunięcia stref czasowych są również nieprzewidywalne. Nie można powiedzieć, że jeśli w 2025 r. „12:00 czasu moskiewskiego” jest nadal „9:00 UTC”, tak jak jest dzisiaj, to zmieniał się kilka razy w ciągu ostatnich 30 lat . Jeśli chcesz wyrazić przyszły czas lokalny, potrzebujesz prawdziwych stref czasowych.
Marten,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.