2012-06-21 45 views
5

我有序列化爲一個字符串 「2012-06-20T13:19:59.1091122Z」 日期轉換DateTimeConverter從UTC串

使用DateTimeConverter,這個被轉換爲DateTime對象{22:49:59.1091122}與Kind屬性設置爲「本地」。

例如。下面的測試失敗:

private static readonly DateTime UtcDate = new DateTime(634757951991091122, DateTimeKind.Utc); 
    private const string UtcSerialisedDate = "2012-06-20T13:19:59.1091122Z"; 

    [Test] 
    public void DateTimeConverter_Convert_From_Utc_String() 
    { 
     // Arrange 
     var converter = TypeDescriptor.GetConverter(typeof(DateTime)); 

     // Act 
     var result = converter.ConvertFrom(UtcSerialisedDate); 

     // Assert 
     Assert.AreEqual(UtcDate, result); 
     Assert.AreEqual(DateTimeKind.Utc, ((DateTime)result).Kind); 
    } 

我有點驚訝於此......我會期望轉換器返回的DateTime對象將在UTC。

該文檔確實說DateTimeConverter使用DateTime.Parse,但我猜它不能使用DateTimeStyles.RoundtripKind選項。

有沒有解決這個辦法嗎?

回答

6

這裏的真正bug是沒有任何DateTimeStyles傳遞的DateTime.Parse()應該仍然看到「Z」並認識到它應該被解析爲UTC。但運氣好讓MS來承認或解決這個問題。

您的代碼示例說明的特定問題是DateTimeConverter必須重寫TypeConverter中的方法,因此無法傳遞額外參數(如DateTimeStyles)。這太糟糕了,它沒有爲此實現某種靜態或線程靜態屬性。它的確利用了線程的Culture.CurrentCulture,但DateTimeStyles與文化是分開的,所以唉 - 這是另一個死路一條。

我假設你被鎖定在使用轉換器,而不是直接調用解析?這是一個很難的要求嗎?如果沒有,你可以做到以下幾點:

public static object ConvertFrom<T>(string value) 
{ 
    if (typeof(T) == typeof(DateTime)) 
    return DateTime.Parse(value, null, DateTimeStyles.RoundtripKind); 

    var converter = TypeDescriptor.GetConverter(typeof(T)); 
    return converter.ConvertFrom(value); 
} 

另一種方法是使用DateTimeOffsetConverter代替 - 它正確地理解在Z時區。然後,您可以使用結果的.UtcDateTime屬性返回UTC類型的DateTime。