2014-04-03 44 views
2

下面的語句打印「1/1/0001下午4時00分〇〇秒-05:00」是否可以爲DateTimeOffset的JSON.NET反序列化指定偏移量?

Console.WriteLine(JsonConvert.DeserializeObject<DateTimeOffset>("\"0001-01-01T16:00:00\"")); 

這是因爲當json.net反序列化一個DateTime字符串(不具有偏移)到DateTimeOffset對象,它分配本地偏移量,在本例中爲-05:00。

如果我不想使用本地偏移?有什麼辦法可以指定一個偏移量用於這種反序列化?

(用例是數據庫服務器和Web服務器處於不同的時區,我需要有區域,不確定的時間讓數據庫服務器反序列化後的偏移傳入的請求。)

更新:我無法控制傳入時間字符串的格式。我有一個具有DateTimeOffset屬性的數據傳輸對象類,我需要將傳入的時間數據存儲到此屬性。

回答

5

你要反序列化到要匹配的數據類型你正在期待。如果您不希望包含偏移量,則不要反序列化爲DateTimeOffset。相反,反序列化爲DateTime。它的.Kind財產將有DateTimeKind.Unspecified

關於Web服務器時區的知識與反序列化的任務無關。所以事後分開應用它。

// deserialize the json 
DateTime dt = JsonConvert.DeserializeObject<DateTime>("\"2014-01-01T00:00:00\""); 

// find your target time zone 
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"); 

// apply the time zone to determine the offset, and create the DateTimeOffset 
DateTimeOffset dto = new DateTimeOffset(dt, tz.GetUtcOffset(dt)); 

更新

每評論,如果你需要做在您所要求的方式來解決此轉換,您需要一個自定義的JSON轉換器。這應該做的伎倆:

public class CustomDateTimeConverter : IsoDateTimeConverter 
{ 
    private readonly string defaultTimeZoneId; 

    public CustomDateTimeConverter(string defaultTimeZoneId) 
    { 
     this.defaultTimeZoneId = defaultTimeZoneId; 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     if (objectType != typeof (DateTimeOffset) && objectType != typeof (DateTimeOffset?)) 
      return base.ReadJson(reader, objectType, existingValue, serializer); 

     var dateText = reader.Value.ToString(); 
     if (objectType == typeof(DateTimeOffset?) && string.IsNullOrEmpty(dateText)) 
      return null; 

     if (dateText.IndexOfAny(new[] { 'Z', 'z', '+'}) == -1 && dateText.Count(c => c == '-') == 2) 
     { 
      var dt = DateTime.Parse(dateText); 
      var tz = TimeZoneInfo.FindSystemTimeZoneById(this.defaultTimeZoneId); 
      var offset = tz.GetUtcOffset(dt); 
      return new DateTimeOffset(dt, offset); 
     } 

     return DateTimeOffset.Parse(dateText); 
    } 
} 

然後你就可以在轉換過程中連線起來:

var settings = new JsonSerializerSettings(); 
settings.DateParseHandling = DateParseHandling.None; 
settings.Converters.Add(new CustomDateTimeConverter(defaultTimeZoneId: "Eastern Standard Time")); 
DateTimeOffset dto = JsonConvert.DeserializeObject<DateTimeOffset>("\"2014-01-01T00:00:00\"", settings); 

請務必使用一個有效的時區ID。不要使用固定的偏移量。

另外,如果您嘗試在沒有日期的情況下傳遞時間,這將不是正確的方法。這是一個完全不同的問題,並通過0001-01-01爲日期不是一個好方法。我很樂意與您討論in chat

+0

嗯,問題是,我們必須支持這兩種類型的時間,區域未指定和區域特定的,具有DateTimeOffset屬性。 – Zoomzoom

+0

而且我無法更正反序列化的DateTimeOffset對象,因爲我無法分辨對象是否帶有偏移量,因此不需要更正,或者它沒有偏移量並且被分配了本地偏移量。 – Zoomzoom

+0

是您的數據合同的一部分 - 您會支持模糊的輸入數據嗎?如果是這樣,我不明白你會如何輕鬆解決它。 –

0

如果您在原字符串(-8:00):偏移

Console.WriteLine(JsonConvert.DeserializeObject<DateTimeOffset>("\"0001-01-01T16:00:00-08:00\"")); 

如果沒有,試試這個

var dateTime = JsonConvert.DeserializeObject<DateTime>("\"0001-01-01T16:00:00\""); 
DateTimeOffset dto = new DateTimeOffset(dateTime, TimeSpan.FromHours(-8)); 
+0

我無法控制傳入的時間字符串。對不起,我會補充說明。 – Zoomzoom

+0

嘗試在解析到'DateTime'後手動添加偏移量。 –

+0

我不行。正如我在另一條評論中提到的那樣,無法確定反序列化的DateTimeOffset對象是否需要更正。我如何知道在反序列化過程中是否添加了偏移量,而不是成爲輸入時間字符串的一部分? – Zoomzoom