2014-11-27 6 views
6

보통 .net에서 시간이있는 경우 DateTimeKind.Unspecified ToLocal을 변환하면 변환 할 때 입력 날짜가 UTC라고 가정합니다. ToUniversal을 변환하는 경우 - 변환 할 때 입력 날짜가 로컬이라고 가정합니다.날짜 시간 '지정되지 않음'의 json.net 직렬화/비 직렬화

그러나 JSON.Net에서 문자열 날짜가 지정되지 않은 경우이 논리가없는 것 같습니다. 아래의 테스트 사례를 살펴 보겠습니다. 제가 잘못하고있는 것입니까? 또는 디자인에 의한 것인가? 또는 JSON.Net의 버그? 감사합니다.

// TODO: This Fails with output 
    //  date string: "2014-06-02T21:00:00.0000000" 
    //  date serialized: 2014-06-02T21:00:00.0000000Z 
    //  Expected date and time to be <2014-06-03 04:00:00>, but found <2014-06-02 21:00:00>. 
    [TestMethod] 
    public void NEW_Should_deserialize_unspecified_datestring_to_utc_date() 
    { 
     string dateString = "\"2014-06-02T21:00:00.0000000\""; 
     DateTime dateRaw = new DateTime(2014, 6, 2, 21, 0, 0, 0, DateTimeKind.Unspecified); 
     DateTime dateRawAsUtc = new DateTime(2014, 6, 3, 4, 0, 0, 0, DateTimeKind.Utc); 
     dateRawAsUtc.Should().Be(dateRaw.ToUniversalTime()); 

     JsonSerializerSettings settings = new JsonSerializerSettings(); 
     settings.DateTimeZoneHandling = DateTimeZoneHandling.Utc; 
     settings.DateFormatHandling = DateFormatHandling.IsoDateFormat; 
     DateTime dateSerialized = JsonConvert.DeserializeObject<DateTime>(dateString, settings);     

     Console.WriteLine("date string: " + dateString); 
     Console.WriteLine("date serialized: " + dateSerialized.ToString("o")); 

     dateSerialized.Kind.Should().Be(DateTimeKind.Utc); 
     dateSerialized.Should().Be(dateRaw.ToUniversalTime()); 
     dateSerialized.Should().Be(dateRawAsUtc); 
    } 

    // TODO: This Fails with output 
    //  date string: "2014-06-02T21:00:00.0000000" 
    //  date serialized: 2014-06-02T21:00:00.0000000-07:00 
    //  Expected date and time to be <2014-06-02 14:00:00>, but found <2014-06-02 21:00:00>. 
    [TestMethod] 
    public void NEW_Should_deserialize_unspecified_datestring_to_local_date() 
    { 
     string dateString = "\"2014-06-02T21:00:00.0000000\""; 
     DateTime dateRaw = new DateTime(2014, 6, 2, 21, 0, 0, 0, DateTimeKind.Unspecified); 
     DateTime dateRawAsLocal = new DateTime(2014, 6, 2, 14, 0, 0, 0, DateTimeKind.Local); 
     dateRawAsLocal.Should().Be(dateRaw.ToLocalTime()); 

     JsonSerializerSettings settings = new JsonSerializerSettings(); 
     settings.DateTimeZoneHandling = DateTimeZoneHandling.Local; 
     settings.DateFormatHandling = DateFormatHandling.IsoDateFormat; 
     DateTime dateSerialized = JsonConvert.DeserializeObject<DateTime>(dateString, settings); 

     Console.WriteLine("date string: " + dateString); 
     Console.WriteLine("date serialized: " + dateSerialized.ToString("o")); 

     dateSerialized.Kind.Should().Be(DateTimeKind.Local); 
     dateSerialized.Should().Be(dateRaw.ToLocalTime()); 
     dateSerialized.Should().Be(dateRawAsLocal); 
    } 

    [TestMethod] 
    public void NEW_Should_deserialize_unspecified_datestring_to_unspecified_date() 
    { 
     string dateString = "\"2014-06-02T21:00:00.0000000\""; // unspecified, does not have the 'Z' 
     DateTime dateRaw = new DateTime(2014, 6, 2, 21, 0, 0, 0, DateTimeKind.Unspecified); 

     JsonSerializerSettings settings = new JsonSerializerSettings(); 
     settings.DateTimeZoneHandling = DateTimeZoneHandling.Unspecified; 
     settings.DateFormatHandling = DateFormatHandling.IsoDateFormat; 
     DateTime dateSerialized = JsonConvert.DeserializeObject<DateTime>(dateString, settings);     

     Console.WriteLine("date string: " + dateString); 
     Console.WriteLine("date serialized: " + dateSerialized.ToString("o")); 
     dateSerialized.Kind.Should().Be(DateTimeKind.Unspecified); 
     dateSerialized.Should().Be(dateRaw); 
    } 
+0

시도를 :

if (dateSerialized.Kind == DateTimeKind.Unspecified) { dateSerialized = dateSerialized.ToUniversalTime(); } 

이 전체, 개정 된 첫 번째 테스트는 다음과 같이하고이 통과된다는 것을 의미합니다 : 당신의 도움의 손길이 놀이로 오는 곳 여기입니다 'DateTime'. 그것은 반드시 deserialize해야합니다. – daramasala

답변

2

나는 당신이 찾고있는 것을 100 % 확신하지만, 나는 JSON.Net가 약간의 도움없이 사용자의 요구 사항을 모두 충족 것이라고 가정하는 것은 안전하지라고 생각합니다. As Mr. Newton says :

JSON의 날짜는 어렵습니다.

우선 여부를 결정하는 것입니다 또는 당신이 지정되지 않은 날짜를 수락하거나 당신이하는 경우가 후행 Z.

누락 된 경우에도 모든 수신 날짜, 보편적 있다고 가정거야 여부를 지원하려는 들어오는 모든 날짜는 보편적 인 것을, 당신은 단지 그들이 후행 Z이 있는지 확인하고,하지 않을 경우, 추가 (생산 코드 정확히,하지만 당신은 아이디어를 얻을) 수있는 가정

if (!dateString.EndsWith("Z\"", StringComparison.InvariantCultureIgnoreCase)) 
{ 
    dateString = dateString.Substring(0, dateString.LastIndexOf("\"", StringComparison.InvariantCultureIgnoreCase)) + "Z\""; 
} 

을 가정의 변화는 않습니다 테스트 할 날짜를 Utc로 수정해야합니다. 와

JsonSerializerSettings settings = new JsonSerializerSettings(); 
settings.DateTimeZoneHandling = DateTimeZoneHandling.Utc; 
settings.DateFormatHandling = DateFormatHandling.IsoDateFormat; 
DateTime dateSerialized = JsonConvert.DeserializeObject<DateTime>(dateString, settings);     

:

들어오는 날짜가 보편적 가정, 대신 지정되지 않은로 처리하지 않으려면

, 당신은 대체하여 들어오는 JSON 변환하는 방법을 변경해야

var oConverter = new Newtonsoft.Json.Converters.IsoDateTimeConverter(); 
DateTime dateSerialized = JsonConvert.DeserializeObject<DateTime>(dateString, oConverter); 

이로 인해 dateString과 정확히 일치하는 날짜가 지정되지 않습니다. 대신`DateTimeOffset`를 사용하는

string dateString = "\"2014-06-02T21:00:00.0000000\""; 
    DateTime dateRaw = new DateTime(2014, 6, 2, 21, 0, 0, 0, DateTimeKind.Unspecified); 
    DateTime dateRawAsUtc = new DateTime(2014, 6, 3, 4, 0, 0, 0, DateTimeKind.Utc); 
    dateRawAsUtc.Should().Be(dateRaw.ToUniversalTime()); 

    var oConverter = new Newtonsoft.Json.Converters.IsoDateTimeConverter(); 
    DateTime dateSerialized = JsonConvert.DeserializeObject<DateTime>(dateString, oConverter); 
    if (dateSerialized.Kind == DateTimeKind.Unspecified) 
    { 
     dateSerialized = dateSerialized.ToUniversalTime(); 
    } 

    Console.WriteLine("date string: " + dateString); 
    Console.WriteLine("date serialized: " + dateSerialized.ToString("o")); 

    dateSerialized.Kind.Should().Be(DateTimeKind.Utc); 
    dateSerialized.Should().Be(dateRaw.ToUniversalTime()); 
    dateSerialized.Should().Be(dateRawAsUtc); 
+0

UGH! ...하지만 확실히 포스트/정보에 대한 감사 ... 이것은 '디자인'에 의한 것입니다 ... 이제, 불특정 지원에 대한 의견은 종종 발생합니다. 개발자 myDate = new DateTime (2014, 10, 23); 나는 이것이 의미하거나 일어나는 일에 대해 예측할 수있는 행동을하고 싶습니다. 그리고 .Net이 그것을 한 가지 방법으로 수행한다면, JSON.Net은 다른 방식으로 그것을합니다. 그것은 ... 못생긴 것입니다 ... 그리고 저는 btw 전에 ServiceStack을 사용하고 있었고, 그들은 닷넷과 동일하다. – Raymond

관련 문제