7

文字列「2012-06-20T13:19:59.1091122Z」としてシリアル化された日付があります

DateTimeConverterを使用して、これは、 Kindプロパティが「Local」に設定されたDateTimeオブジェクト{22:49:59.1091122}に変換されます。

例えば。次のテストは失敗します。

    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オプションを使用してはいけないと思います。

これを回避する方法はありますか?

4

1 に答える 1

8

ここでの本当のバグは、DateTimeStylesが渡されていないDateTime.Parse()が引き続き「Z」を認識し、UTCとして解析される必要があることを認識することです。しかし、MSにそれを認めさせるか修正してもらう幸運を祈ります。

コードサンプルで示されている特定の問題は、DateTimeConverterがTypeConverterのメソッドをオーバーライドする必要があるため、DateTimeStylesなどの追加のパラメーターを渡すことができないことです。このためにある種の静的またはthreadstaticプロパティを実装していないのは残念です。それは確かにスレッドのCulture.CurrentCultureを利用しますが、DateTimeStylesは文化とは別のものなので、残念ながら、それはもう1つの行き止まりです。

解析を直接呼び出すのではなく、コンバーターの使用に縛られていると思いますか?これは難しい要件ですか?そうでない場合は、次のようにすることができます。

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に戻ることができます。

于 2012-09-17T20:33:03.650 に答える