2017-02-01 3 views
-1

У меня есть простой проект WebAPI. Я прохожу дату JSON в формате Epoch «pickupBefore»: «/ Date (1485360480-0800) /». Когда .Net ловит его, DateTime показывает год 1970. Предполагается, что это будет 25 января 2017. Что делать, чтобы получить его в режиме реального времени?JSON to .Net Эпоха преобразования даты

В моем приложении .Net я использую дату DateTime. За сценой структура DateTime заполняется датой 1970 года. Я искал что-то в этой структуре, которая поможет мне преобразовать ее в DateTime в реальном времени.

Прежде чем задать вопрос, я попытался ответить How do you convert epoch time in C#?, но это не помогло решить мою проблему. Спасибо

+0

http: // stackoverflow.com/questions/2883576/how-do-you-convert-epoch-time-in-c – Coder14

+3

Возможный дубликат [Как вы конвертируете время эпохи в C#?] (http://stackoverflow.com/questions/2883576/how -do-ты конвертирование-эпохальное время-в-с) – Coder14

ответ

2

Основная проблема заключается в том, что ваша строка даты в Unix время эпохи в секунд но формат даты JSON от Microsoft в Unix время эпохи в миллисекундах, как описано в the documentation. Json.NET автоматически распознает строки дат в формате Microsoft и, таким образом, интерпретирует смещение как ms, а не секунды, что объясняет, почему DateTime показывает год 1970, так как 1970 год является годом начала эпохи Unix.

Вы должны исправить свой JSON так, чтобы формат даты полностью соответствовал формату Microsoft, который был бы "/Date(1485360480000-0800)/". Еще лучше, вы можете переключиться на ISO 8601 format, который в настоящее время является предпочтительным форматом JSON для дат и времени в любом случае.

Если по каким-либо причинам вы не можете исправить формат JSON, вам нужно будет отключить автоматический DateTime признание и синтаксический Json.NET, и создать свой собственный custom JsonConverter унаследовав от DateTimeConverterBase.

Чтобы отключить автоматическое распознавание даты Json.NET, установите DateParseHandling = DateParseHandling.None в JsonSerializerSettings. Но если вы не можете изменить ваши общие настройки Serializer, вы можете отключить распознавание даты на вмещающий типе только с применением преобразователя от Question 40632820 к нему, например .:

[JsonConverter(typeof(DateParseHandlingConverter), DateParseHandling.None)] // Disable Json.NET's built-in date time parsing function. 
public class RootObject 
{ 
    public DateTime pickupBefore { get; set; } 
} 

Далее вам нужно будет написать свой обычай JsonConverter. Одним из вариантов было бы дублирование всей логики Newtonsoft DateTimeUtils.TryParseDateTime() и DateTimeUtils.TryParseDateTimeOffset(), в процессе перезаписи DateTimeUtils.TryParseDateTimeMicrosoft() и DateTimeUtils.TryParseDateTimeOffsetMicrosoft() для анализа номеров эпох в секундах, а не в миллисекундах. Я начал это делать, но понял, что есть достаточный объем кода - это больше, чем подходит для ответа stackoverflow. В качестве альтернативы, быстрый и грязный хак будет вставить дополнительный 000 подстроку в формате JSON для преобразования от нескольких секунд до миллисекунд, например, так:

public class MicrosoftSecondsDateTimeConverter : DateTimeConverterBase 
{ 
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     if (reader.TokenType == JsonToken.Null) 
      return null; 
     var token = JToken.Load(reader); 
     if (token.Type == JTokenType.String) 
     { 
      var s = ((string)token).Trim(); 
      if (s.StartsWith("/Date(", StringComparison.Ordinal) && s.EndsWith(")/", StringComparison.Ordinal)) 
      { 
       // MS datetime format is in milliseconds as is shown here: 
       // https://msdn.microsoft.com/en-us/library/bb299886.aspx#intro_to_json_sidebarb 
       // But our times are offsets in seconds. 
       // Convert. 
       var sb = new StringBuilder("\"\\/Date("); 
       var insert = "000"; // Seconds to MS 
       for (int i = 6; i < s.Length - 2; i++) 
       { 
        if (s[i] == '-' || s[i] == '+') // Time zone marker 
        { 
         sb.Append(insert); 
         insert = string.Empty; 
        } 
        sb.Append(s[i]); 
       } 
       sb.Append(insert); 
       sb.Append(")\\/\""); 
       s = sb.ToString(); 
       var dt = new JsonSerializer().Deserialize(new StringReader(s), objectType); 
       return dt; 
      } 
     } 

     // Not a Microsoft date. 
     return new JsonSerializer().Deserialize(token.CreateReader(), objectType); 
    } 

    public override bool CanWrite { get { return false; } } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 
} 

Это не красиво, но делает получить работу. Затем применить конвертер для вашего типа следующим образом:

[JsonConverter(typeof(DateParseHandlingConverter), DateParseHandling.None)] // Disable Json.NET's built-in date time parsing function. 
public class RootObject 
{ 
    [JsonConverter(typeof(MicrosoftSecondsDateTimeConverter))] 
    public DateTime pickupBefore { get; set; } 
} 

Или добавить его в JsonSerializerSettings.Converters изменить десериализацию DateTime строк для всех вашей модели данных.

Образец fiddle.

Смежные вопросы