2013-10-30 54 views
16

我有一個POCO這樣的:ServiceStack - 有沒有辦法強制所有序列化日期使用特定的DateTimeKind?

public class BlogEntry 
{ 
    public string Title { get; set; } 
    public DateTime Date { get; set; } 
} 

大部分的它正在從實體框架水合的時間,但它能夠而且將實體框架之外使用。

來自EF的日期的DateTimeKind是未指定的,從我讀的是正常的。

當我在Redis中緩存這個POCO時(使用ServiceStack Redis客戶端),它返回一個DateTimeKind本地。

因此返回的對象存在抖動。第一遍(未緩存)的ISO-8061沒有偏移量(DateTimeKind.Unspecified)。第二遍(緩存)是帶有偏移量的ISO-8061(來自Redis和DateTimeKind.Local)。

任何方式強制ServiceStack JSON序列化程序總是將日期解釋爲給定的DateTimeKind? (我知道有一個「JsConfig.AppendUtcOffset」屬性,但不管它是真是假,這些數值對我來說永遠不會改變嗎?)

或者在我的類型化的RedisClient的反序列化過程中的某個地方使DateTimeKind本地?

我可以手動更改我的POCO來強制執行DateTimeKind - 而且工作正常 - 但我希望減少出錯的機率。

回答

16

如果你需要比@ mythz的回答更多的東西可配置的,你可以通過重寫強制DateTime是否的序列化和反序列化有一定DateTimeKind DateTime和可選的DateTime?序列化和/或反序列化方法。

強制所有的序列化DateTime是否被解釋爲UTC

JsConfig<DateTime>.SerializeFn = time => new DateTime(time.Ticks, DateTimeKind.Local).ToString(); 

然後,您可以藉此一步和錯誤的反序列化,如果日期時間是不是按照規定的格式。當我想強制客戶端在所有請求中指定時區時,我開始使用它,但不一定要求它始終是Utc。

JsConfig<DateTime>.DeSerializeFn = time => 
{ 
    if (!IsInCorrectDateFormat(time)) 
    throw new System.Runtime.Serialization.SerializationException(BadDateTime); 

    return ServiceStack.Text.Common.DateTimeSerializer.ParseDateTime(time); 
}; 
+0

爲什麼我的設置中沒有調用'JsConfig .SerializeFn'委託的任何想法? – ygormutti

+1

你是否用可空的DateTime調用序列化? –

+0

對於那些沒有立即找到ygormutti解決方案的人...您只需要做:'JsConfig .SerializeFn' –

6

DateTimeKind offset不會與Date一起存儲,所以默認情況下,ServiceStack序列化器假定日期是本地的,它被序列化爲UTC並反序列化爲本地。

你可以得到DateTimeKind.Unspecified被假定爲與UTC:

JsConfig.AssumeUtc = true; 
+0

接通您的建議,它非常接近爲我工作。第一個呼叫示例:「2013-07-19T12:49:52.5570000」,第二個呼叫示例:「2013-07-19T19:49:52.5570000Z」。從技術上講,任何語言都應該可以解析,並且我假設它們都是相同的,但是我有強烈的願望讓它們完美匹配。 – ryan1234

+0

如果我想將它們假定爲'DateTimeKind.Local',該怎麼辦?DateTime序列化程序正在返回本地時間,就像它是UTC一樣。 'JsConfig.AssumeUtc = false;'不起作用。 – ygormutti

+1

這適用於JSON - 是否有JSV的等價物? – Cocowalla

5

對bpruitt-goddard解決方案進行調整。所有的榮譽歸功於他。

JsConfig<DateTime>.SerializeFn = time => new DateTime(time.Ticks, DateTimeKind.Local).ToString("o"); 
     JsConfig<DateTime?>.SerializeFn = 
      time => time != null ? new DateTime(time.Value.Ticks, DateTimeKind.Local).ToString("o") : null; 
     JsConfig.DateHandler = DateHandler.ISO8601; 

所以從服務棧走出去的任何日期將被迫進入一個ISO8601日期格式,並在未來的任何日期將從ISO8601字符串自動轉換爲C#日期。

相關問題