JavaScript'te bir Date nesnesi almak için JSON nasıl ayrıştırılır?


117

Aşağıdaki bir JSON parçam var:

\/Date(1293034567877)\/

bu .NET kodunun bir sonucudur:

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

Şimdi karşı karşıya olduğum sorun, JavaScript'te bundan bir Date nesnesinin nasıl oluşturulacağıdır. Tek bulabildiğim inanılmaz normal ifade çözümüydü (çoğu hata içeren).

Tüm bunlar JavaScrip'te olduğu için zarif bir çözüm olmadığına inanmak zor, yani JavaScript kodu olduğu varsayılan JSON'u (JavaScript Object Notation) okumaya çalışan JavaScript kodu ve şu anda JavaScript'in yapamayacağı bir şey olmadığı ortaya çıktı. burada iyi bir iş çıkar.

Çalışmak için yapamadığım bazı değerlendirme çözümleri de gördüm (güvenlik tehdidi olarak gösterilmesinin yanı sıra).

Bunu zarif bir şekilde yapmanın gerçekten bir yolu yok mu?

Gerçek yanıtı olmayan benzer soru:
GWT ile ASP.NET JSON Tarih biçimi nasıl ayrıştırılır


2
Zaman damgasını müşteriye iletebilir ve new Date()onu arayabilirsiniz .
jAndy

Zaman
damgam

Yanıtlar:


51

Tarihlerin standart JSON gösterimi yoktur. @JAndy'nin önerdiği şeyi yapmalı ve a'yı serileştirmemelisiniz DateTime; yalnızca bir RFC 1123 tarih dizesi ToString("r")veya Unix-epoch'tan bir saniye numarası veya JavaScript'te bir Date.


3
Teşekkürler Ölü bir yoldan gidiyordum, JSON'un Tarih türünü desteklemediğini ilk belirten sizdiniz.
Piotr Owsiak

3
JSON sayıları, dizeleri, nesneleri, dizileri ve true, false ve null değişmezlerini destekler. Tarih bunlardan hiçbiri olmadığından, bir dizeden ziyade bir nesne olarak depolanması gereken karmaşık bir türdür, bu nedenle, "$ type" gibi özel üyelerde tür adı gibi tür bilgilerini asla bir gerçek nesne üyesi. Bu tür meta üyeler, JSON nesnesini daha sonra türü kesin belirlenmiş bir çalışma zamanı nesnesine dönüştürmek için kullanılabilir. Bir dizeye tarih yapıştırmanın aptalca olduğunu düşünüyorum, çünkü gereksiz yere ayrılmış dizgi kalıpları oluşturuyor ve bunları her dizede eşleştirmeye çalışıyor.
Triynko

4
Artık standart bir JSON tarih biçimi var. tools.ietf.org/html/rfc7493#section-4.3
Bryan Larsen

128

JSON.parseFonksiyonu, isteğe bağlı DateTime kuvvetlendirici işlevi kabul eder. Bunun gibi bir işlevi kullanabilirsiniz:

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

Sonra ara

JSON.parse(somejsonstring, dateTimeReviver);

Ve tarihleriniz doğru çıkacak.


1
İyi tespit edildi, oldukça kullanışlı.
noup

5
İlkel olmayan tipteki verileri ilkel bir tipte (dize) kodlama uygulaması deliliktir. Bir JSON nesnesindeki tarihleri ​​anlamlı özelliklerle kodlayın veya daha da ileri gitmek için JSON nesnesine bir "$ type" özelliği ekleyin, böylece ayrıştırma / seriyi kaldırma yordamı türü uygun şekilde yeniden canlandırabilir ve hatta tümünü paketlemek istiyorsanız özel dönüştürücüler kullanabilir bilgileri "işaretler" veya "ms_since_epoch" gibi tek bir özellik değerine yerleştirin.
Triynko

7
Normal ifadeyi / \ / Date ((-? \ D *)) \ // gibi değiştirmem gerekiyordu, böylece negatif sayıları da işleyebilecekti. Negatif sayılar, .NET tarafından JSON'a dönüştürülmüş çok eski bir DateTime (Epoch'tan önce) olduğunda görünür.
ClearCloud8

@ ClearCloud8: Eğik çizgileri kaçırdınız: / \ / Date \ ((-? \ D *) \) \ //
Jerther

1
Bu işlevi hiç bilmiyordum - bu çok kullanışlı!
keldar

50

Roy Tinker'in bu cevabı burada :

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

Dediği gibi: substr işlevi "/ Date (" bölümünü çıkarır ve parseInt işlevi tamsayıyı alır ve sonunda ") /" öğesini yok sayar. Ortaya çıkan sayı, Tarih yapıcısına aktarılır.

Diğer bir seçenek, bilgilerinizi ASP tarafında, JavaScript'in kolayca okuyabileceği şekilde biçimlendirmektir. Bunu tarihleriniz için yapmayı düşünün:

DateTime.Now()

Bunun gibi bir biçim döndürmesi gereken:

7/22/2008 12:11:04 PM

Bunu bir JavaScript'e aktarırsanız Date gibi kurucusuna :

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

Değişken date artık şu değeri tutar:

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

Doğal olarak, bu DateTimenesneyi, JS Dateyapıcısının kabul ettiği herhangi bir dize / int türünde biçimlendirebilirsiniz .


Teşekkürler treeface, bu cevap son zamanlarda bana yardımcı oldu!
Malice

4
Asla, asla, varsayılan tarih <-> dize dönüştürme biçimlerine güvenmeyin. Sayısal türler alanında kalan Epoch'tan bu yana milisaniye kullanmak çok daha basit ve güvenilirdir.
Johan Boulé

2
Bu cevap iki çözüm sunar - birincisi doğru (ayrıştırıcı) ve ikincisi yanlış, bu yüzden yukarı veya aşağı oy mu vereceğinizden emin değilsiniz! Yalnızca bir dizge olarak çıktı alma ile ilgili sorun, tarihin, sunucu bir ülkedeyse, örneğin ABD ve tarayıcı başka bir ülkedeyse, örneğin İngiltere ise kolaylıkla geriye doğru dönebilmesidir.
mike nelson

Bana herhangi bir ipucu verecek ilk cevap
Nick.McDermaid

" Tarihleriniz için bunu yapmayı düşünün… " seçeneğine kadar Tamam bir yanıt . Uygulamaya bağlı ayrıştırma ve saat dilimi sorunlarını ortaya çıkaran standart olmayan bir biçim önermek iyi bir fikir değildir. OP biçimi tercih edilir (ideal olmasa da).
RobG

21

Eğer JSON JavaScript tarzı ISO8601 tarihini kullanıyorsanız, gelen bu kullanabilirsiniz MDN'yi

var jsonDate = (new Date()).toJSON();
var backToDate = new Date(jsonDate);
console.log(jsonDate); //2015-10-26T07:46:36.611Z

2
imo bu en zarif cevaptır ve kabul edilen cevap olmalıdır.
John

1
Gerçekten çok zarif, ancak bu, soruda bahsedilen belirli tarih formatıyla ilgili değil.
asiop

@aslop - kullanıcı bir tarihi ISO'ya / ISO'dan dönüştüremiyorsa, JSON sorunların en küçüğüdür.
LeeGee

7

JSON Tarihini JavaScript'te normal tarih biçimine dönüştürebilirsiniz.

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

6

Sorun ne:

new Date(1293034567877);

Bu bana "22 Aralık 2010 Çarşamba 16:16:07 GMT + 0000 (GMT Standart Saat)" döndürür.

Veya numarayı json'dan almanız mı gerekiyor?


3
Çözümünüzün nesi var? Peki 1293034567877 benim sahip olduğum JSON değil, değil mi? Ayrıca JSON'dan numarayı almam gerekmiyor, Tarihi JSON'dan almam gerekiyor. JavaScript'ten normal ifadeyle her şeyi yapabilmekten biraz daha fazlasını bekliyorum. Kodumun okunabilir olması ve çizgi film laneti gibi görünmemesi gerekiyor.
Piotr Owsiak

7
.NET gibi garip bir formatta bir tarih nesnesinin serileştirilmesini ürettiği için .NET'i suçlardım \/Date(1293034567877)\/. Aklı başında olsaydı, sadece epoch zamanını verirdi ve bununla bir Date nesnesi başlatabilirdiniz.
Quentin

2
@treeface: JSON JavaScript değilse, bu yaygın yanlış anlaşılmadan öğreticiler ve kitapların suçlanacağını düşünüyorum. Her neyse, gerçekten düzeltilmiş olmaktan memnuniyet duyarım. Tarihin String olarak temsil edilebileceği önerinize gelince, her şeyin String olarak temsil edilebileceğini söyleyebilirim, değil mi? Ancak bu, işimizi kolaylaştırmaz, ama son derece acı verici ve cehennem gibi. Sanırım sorunum JSON'u bir serileştirme formatı olarak düşünmemden kaynaklanıyor (daha az bant genişliği alması ve JavaScript ile XML'den daha iyi çalışması için ilan edildi). Görünüşe göre değil, en azından ağrısız değil.
Piotr Owsiak

1
@treeface: JSON hakkındaki iddianızı google'da yaptım ve JSON'un JavaScript olduğunu, aslında JavaScript'in bir alt kümesi olduğunu öğrendim. RFC # 4627 "JavaScript Nesne Gösterimi (JSON) için uygulama / json Medya Türü" konusuna bakın ve şu ifadeyi arayın: "JSON'un tasarım hedefleri minimum, taşınabilir, metinsel ve bir JavaScript alt kümesi olmasıydı.". Şimdi bunu düşündüğümde, JSON'da eval () çağırabileceğiniz için apaçık görünüyor.
Piotr Owsiak

1
@David Dorward: Eklenen karmaşıklığın programcı tarafından işlenecek ayrıntıyı bırakmak yerine kitaplıkların derinliklerinde (.NET, Java, Ruby, Python veya hangi dil / platformda olursanız olun) uygulanmasını tercih ederim. Ayrıca JSON'da boole ve tamsayı veri türleri desteğine ihtiyacınız olmadığını unutmayın, bunları dizelere koyabilirsiniz, değil mi? O halde JSON'dan herhangi bir şey almanın ne kadar kötü olacağını hayal edebiliyor musunuz?
Piotr Owsiak

2

Bunun çok eski bir konu olduğunu biliyorum, ancak bunu benim yaptığım gibi karşılaşanlara yardımcı olmak için göndermek istiyorum.

3. parti komut dosyası kullanmayı umursamıyorsanız , moment, js komutunu kullanabilirsiniz. Daha sonra .format () kullanarak istediğiniz herhangi bir şeyi biçimlendirebilirsiniz.


2

Tarihler her zaman bir kabustur. Eski sorunuzu yanıtlamak, belki de en zarif yol:

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

Eval ile dizimizi javascript koduna dönüştürürüz. Daha sonra "/" karakterini kaldırıyoruz, yerine işlev düzenli bir ifadedir. Yeni ile başladığımızda, cümlelerimiz bunu uygulayacaktır:

new Date(1455418800000)

Şimdi, uzun zaman önce kullanmaya başladığım bir şey, kenelerle temsil edilen uzun değerler ... neden? yerelleştirme ve her sunucuda veya her istemcide tarihin nasıl yapılandırıldığını düşünmeyi bırakın. Aslında onu veritabanlarında da kullanıyorum.

Belki bu cevap için oldukça geç, ama buradaki herkese yardımcı olabilir.


Btw, yıllarca ingilizcem hiç olmadığı kadar kötüleşiyor ... ama sanırım kendimi anlamıştım.
Gabriel Andrés Brancolini

Cevabınız harika çalışıyor, sıkıntıdan kurtulmama yardımcı oldu. Teşekkürler.
BoredBsee

1

AngularJS, .NET JSON tarihini ayrıştıramadı /Date(xxxxxxxxxxxxx)/ dizesini ..

Ben, bu sorunu, tarihi, dökümünü atmak yerine ISO 8601 dize gösterimine biçimlendirerek aştım. Date nesneyi doğrudan ...

İşte ASP.NET MVC kodunun bir örneği ..

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

Denedim RFC 1123ama işe yaramıyor .. Angular bunu Date yerine string olarak ele alıyor.

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

0

Bunun gibi şeyler için .Net kullanmadım. Aşağıdaki gibi bir şey yazdırmayı başardıysanız, çalışmalıdır.

Bu JSON dizesini başka bir yöntemle ayrıştırmıyorsanız veya yalnızca kullanıcıların yerleşik bir JSON ayrıştırıcısına sahip modern tarayıcılara sahip olmasını beklemiyorsanız, sunucu tarafından çıkarılan JSON dizesini gerçek bir JSON'a ayrıştırmak için bir JS çerçevesi veya JSON2 kullanmanız gerekir. nesne.

// 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 Bağlantısı

Firefox 3.5 ve Internet Explorer 8 gibi modern tarayıcılar, JSON'u ayrıştırmak için özel özellikler içerir. Yerel tarayıcı desteği eval () 'dan daha verimli ve güvenli olduğundan, yerel JSON desteğinin bir sonraki ECMAScript standardına dahil edilmesi beklenmektedir. [6]


JSON2 dosyasına bağlantı

Canlı Örnek


Anlıyorum, ancak JSON ve Tarih türü ile ilgili sorunum, tüketiciye iletilmesi gereken "yeni Tarih (" a) fazladan iş b) ek bilgi parçasını açıkça yapmam gerektiğidir. Bunun nasıl işlendiğini öğrendiğim için gerçekten hayal kırıklığına uğradım ve temelde JSON spesifikasyonunda bir hata olduğunu düşünüyorum.
Piotr Owsiak

0

Bu sorunun cevabı, JSON.NET'i elde etmek için nuget kullanın ve ardından bunu JsonResultyönteminizin içinde kullanın :

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

bakış açınız içinde bunu basitçe yapın javascript:

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

Bir ajax çağrısıysa:

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

Bir kez JSON.parseçağrıldıktan sonra , JSON tarihini bir new Dateörneğe koyabilirsiniz çünkü JsonConvertuygun bir ISO zaman örneği oluşturur


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

0

Callum'un da bahsettiği gibi, benim için en iyi yol, Controller yöntemini JsonResult yerine string olarak değiştirmektir ".

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

Ajax yönteminden böyle bir şey yapabilirsiniz

 $.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))
}
});

0

eval işlevini kullanmak çalışırsa sadece öndeki ve arkadaki eğik çizgiyi kaldırmanız gerekir.

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

verim 01 Ocak 1970 00:00:00 GMT-0700 (ABD Dağ Standart Saati)


0

Bu formatta tarih sağlayan harici API ile ilgili bir sorunla karşılaştım, hatta bazen UTC fark bilgisi gibi /Date(123232313131+1000)/. DateAşağıdaki kodla js nesnesini çevirebildim

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

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

2
Kodu anladığım kadarıyla, bir tarih nesnesi döndürmüyorsunuz.
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;
};

// Bu işlevi kullanın

var objDate=parseJsonDate("\/Date(1443812400000)\/");
alert(objDate);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.