2011-04-15 28 views
6

Veritabanında bir tarihim var ve bunu Entity Framework kullanarak veritabanından aldım, ardından verileri DataContractJsonSerializer aracılığıyla JSON API aracılığıyla iletiyorum.DataContractJsonSerializer DateTime örtülü zaman dilimi dönüşümü

Tarih saat alanındaki zaman, DataContractJsonSerializer'da işlenirken sunucunun yerel saat dilimine göre ayarlanmış gibi görünüyor. Çağın ifade edilen süresi beklenen sürenin 1 saat ilerisindedir. DateTime Kind UTC'dir, ancak daha önce belirtilmemiş ve aynı sorunu yaşadım.

Uygulamamda, saat dilimleri arasında açıkça ve istemci tarafında değil, sunucuda dönüşüm yapmak istediğimden daha fazla anlam ifade ediyor. Bu örtük işlevlere şaşırdım, datetime değerlerim bir tamsayı gibi basit değerler olmalıdır. senin DateTime.Kind Yerel VEYA Tanımlanmamış eşitse

sayesinde

cevap

4

DataContractJsonSerializer irade çıkışı saat dilimi kısmı (+ zzzz). Bu davranış, Tür, Belirtilmemiş'e eşitse, yalnızca saat dilimi bölümünü çıkaran XmlSerializer'dan farklıdır. Benim makinede beklenen çıktı üretir

var jsonSerializer = new DataContractJsonSerializer(typeof(DateTime)); 
var date = DateTime.UtcNow; 
     Console.WriteLine("original date = " + date.ToString("s")); 
     using (var stream = new MemoryStream()) 
     { 
      jsonSerializer.WriteObject(stream, date); 

      stream.Position = 0; 
      var deserializedDate = (DateTime)jsonSerializer.ReadObject(stream); 
      Console.WriteLine("deserialized date = " + deserializedDate.ToString("s")); 

     } 

aşağıdaki testi koşuyoruz

internal override void WriteDateTime(DateTime value) 
    { 
     // ToUniversalTime() truncates dates to DateTime.MaxValue or DateTime.MinValue instead of throwing 
     // This will break round-tripping of these dates (see bug 9690 in CSD Developer Framework) 
     if (value.Kind != DateTimeKind.Utc) 
     { 
      long tickCount = value.Ticks - TimeZone.CurrentTimeZone.GetUtcOffset(value).Ticks; 
      if ((tickCount > DateTime.MaxValue.Ticks) || (tickCount < DateTime.MinValue.Ticks)) 
      { 
       throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
        XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.JsonDateTimeOutOfRange), new ArgumentOutOfRangeException("value"))); 
      } 
     } 

     writer.WriteString(JsonGlobals.DateTimeStartGuardReader); 
     writer.WriteValue((value.ToUniversalTime().Ticks - JsonGlobals.unixEpochTicks)/10000); 

     switch (value.Kind) 
     { 
      case DateTimeKind.Unspecified: 
      case DateTimeKind.Local: 
       // +"zzzz"; 
       TimeSpan ts = TimeZone.CurrentTimeZone.GetUtcOffset(value.ToLocalTime()); 
       if (ts.Ticks < 0) 
       { 
        writer.WriteString("-"); 
       } 
       else 
       { 
        writer.WriteString("+"); 
       } 
       int hours = Math.Abs(ts.Hours); 
       writer.WriteString((hours < 10) ? "0" + hours : hours.ToString(CultureInfo.InvariantCulture)); 
       int minutes = Math.Abs(ts.Minutes); 
       writer.WriteString((minutes < 10) ? "0" + minutes : minutes.ToString(CultureInfo.InvariantCulture)); 
       break; 
      case DateTimeKind.Utc: 
       break; 
     } 
     writer.WriteString(JsonGlobals.DateTimeEndGuardReader); 
    } 

:

meraklı çek dışarı aşağıdaki yöntemi içerir JsonWriterDelegator için kaynak varsa

original date = 2011-04-19T10:24:39 
deserialized date = 2011-04-19T10:24:39 

Böylece bir noktada Tarihiniz Belirtilmemiş veya Lo olmalıdır. cal. DB dışına çekerek sonra

entity.Date = DateTime.SpecifyKind(entity.Date, DateTimeKind.Utc); 

arayarak Utc için Tanımlanmamış gelen türlü dönüştürmek ve geri ben

+0

Myl var gibi nesnesine SpecifyKind dönüş değeri atamak unutmayın datetime, 1303500600000 + 0000 – krisdyson

+0

için serileştirilmiştir. Numuneniz "\/Date (1303220156217) \ /" ile serileştirilirken, benimki "\/Date (1303500600000 + 0000) \ /" dizinleşir. +0000 – krisdyson

+1

neden dahil olduğunu bilmiyorum DateTimeKind = UTC? Sadece makinemde tekrar denedim ve DateTimeKind UTC (Yerel veya Belirtilmemiş) ile eşit DEĞİL zaman dilimi çıktığında. Sadece kaynak koduna baktım ve eğer DateTimeKind == UTC – wal

İlgili konular