7

我有一个日期序列化为字符串“2012-06-20T13:19:59.1091122Z”

使用DateTimeConverter,这将转换为 DateTime 对象 {22:49:59.1091122} ,其Kind属性设置为“Local”。

例如。以下测试失败:

    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。太糟糕了,它没有为此实现某种静态或线程静态属性。它确实利用了线程的 Culture.CurrentCulture,但 DateTimeStyles 是与文化不同的东西,所以唉 - 这是另一个死胡同。

我假设您被锁定在使用转换器,而不仅仅是直接调用 parse?这是一个硬性要求吗?如果没有,您可以执行以下操作:

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);
}

另一种方法是使用 aDateTimeOffsetConverter代替 - 它正确理解 Z 时区。然后,您可以使用.UtcDateTime结果的属性返回到具有 UTC 类型的 DateTime。

于 2012-09-17T20:33:03.650 回答