gpt4 book ai didi

datetime - 使用 DateTimeStyles.AssumeUniversal 时,为什么 JsonConvert 会使用 DateTimeKind.Unspecified 更改 DateTimes 的时间?

转载 作者:行者123 更新时间:2023-12-03 06:23:46 26 4
gpt4 key购买 nike

我正在构建一个 Web API,但在 DateTimes 的 JSON 序列化方面遇到问题。经过一些测试后,我只能得出结论,Newtonsoft.Json.JsonConvert 和/或 Newtonsoft IsoDateTimeConverter 的行为不是我所期望的。

考虑一下:

// Arrange
var noonUtc = new DateTime(2016, 05, 12, 12, 0, 0, DateTimeKind.Utc);
var noon = new DateTime(2016, 05, 12, 12, 0, 0, DateTimeKind.Unspecified);

var settings = new JsonSerializerSettings();

settings.Converters.Add(new IsoDateTimeConverter
{
Culture = CultureInfo.InvariantCulture,
DateTimeStyles = DateTimeStyles.AdjustToUniversal
});

// Act
var utcJson = JsonConvert.SerializeObject(noonUtc, settings); // "\"2016-05-12T12:00:00Z\""
var json = JsonConvert.SerializeObject(noon, settings); // "\"2016-05-12T10:00:00Z\""

... // Assertions

好的,DateTimeDateTimeKind.Unspecified 的时间已从 12 点调整为 10 点。我在斯德哥尔摩,目前比 UTC 早两个小时,所以很公平。

但是,让我们更改序列化器设置以使用 DateTimeStyles.AssumeUniversal,如下所示:

settings.Converters.Add(new IsoDateTimeConverter
{
Culture = CultureInfo.InvariantCulture,
DateTimeStyles = DateTimeStyles.AssumeUniversal
});

这会产生完全相同的字符串,因此也会将 DateTimeDateTimeKind.Unspecified 调整两个小时!难道不应该假设日期时间已经是 UTC 时间并保持原样吗?我在这里缺少什么?

最佳答案

我认为你没有遗漏任何东西;这看起来可能是 IsoDateTimeConverter 中的一个错误。这是来自 source 的相关代码:

if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal
|| (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal)
{
dateTime = dateTime.ToUniversalTime();
}

如您所见,在调用 ToUniversalTime()< 之前,它仅查看 _dateTimeStyles 是否设置为 AdjustToUniversalAssumeUniversal/;它从不检查日期的 Kind 属性。

DateTime.ToUniversalTime() 的文档是这样说的:

Starting with the .NET Framework version 2.0, the value returned by the ToUniversalTime method is determined by the Kind property of the current DateTime object. The following table describes the possible results.

Kind        | Results
----------- | ----------------------------------------------------------
Utc | No conversion is performed.
Local | The current DateTime object is converted to UTC.
Unspecified | The current DateTime object is assumed to be a local time,
| and the conversion is performed as if Kind were Local.

所以,是的,在这种情况下转换器绝对不应该调用 ToUniversalTime。您可能想要report an issue .

目前,您可以通过实现具有正确行为的替换转换器(从原始转换器派生)来解决此问题。这可能更接近您想要的:

public class CorrectedIsoDateTimeConverter : IsoDateTimeConverter
{
private const string DefaultDateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK";

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value is DateTime)
{
DateTime dateTime = (DateTime)value;

if (dateTime.Kind == DateTimeKind.Unspecified)
{
if (DateTimeStyles.HasFlag(DateTimeStyles.AssumeUniversal))
{
dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc);
}
else if (DateTimeStyles.HasFlag(DateTimeStyles.AssumeLocal))
{
dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Local);
}
}

if (DateTimeStyles.HasFlag(DateTimeStyles.AdjustToUniversal))
{
dateTime = dateTime.ToUniversalTime();
}

string format = string.IsNullOrEmpty(DateTimeFormat) ? DefaultDateTimeFormat : DateTimeFormat;
writer.WriteValue(dateTime.ToString(format, Culture));
}
else
{
base.WriteJson(writer, value, serializer);
}
}
}

关于datetime - 使用 DateTimeStyles.AssumeUniversal 时,为什么 JsonConvert 会使用 DateTimeKind.Unspecified 更改 DateTimes 的时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37203207/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com