gpt4 book ai didi

c# - DataContractJsonSerializer DateTime 隐式时区转换

转载 作者:太空狗 更新时间:2023-10-29 20:28:56 27 4
gpt4 key购买 nike

我在数据库中有一个日期时间,我使用 Entity Framework 从数据库中检索它,然后我通过 DataContractJsonSerializer 通过 JSON API 传递数据。

在 DataContractJsonSerializer 中处理时,日期时间字段中的时间似乎已根据服务器的本地时区进行了调整。纪元表示时间比预期时间提前 1 小时。 DateTime Kind 是 UTC,但之前它是未指定的,我遇到了同样的问题。

在我的应用程序中,我希望在客户端而不是服务器端显式地在时区之间进行转换,因为这更有意义。我对这种隐式功能感到惊讶,因为我的日期时间值应该是像整数一样的简单值。

谢谢

最佳答案

如果您的 DateTime.Kind 等于 Local OR Unspecified,

DataContractJsonSerializer 将输出时区部分 (+zzzz)。此行为不同于 XmlSerializer,后者仅在 Kind 等于 Unspecified 时输出时区部分。

如果好奇,请查看包含以下方法的 JsonWriterDelegator 的源代码:

 internal override void WriteDateTime(DateTime value) 
{
// ToUniversalTime() truncates dates to DateTime.MaxValue or DateTime.MinValue instead of throwing
// This will break round-tripping of these dates (see bug 9690 in CSD Developer Framework)
if (value.Kind != DateTimeKind.Utc)
{
long tickCount = value.Ticks - TimeZone.CurrentTimeZone.GetUtcOffset(value).Ticks;
if ((tickCount > DateTime.MaxValue.Ticks) || (tickCount < DateTime.MinValue.Ticks))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.JsonDateTimeOutOfRange), new ArgumentOutOfRangeException("value")));
}
}

writer.WriteString(JsonGlobals.DateTimeStartGuardReader);
writer.WriteValue((value.ToUniversalTime().Ticks - JsonGlobals.unixEpochTicks) / 10000);

switch (value.Kind)
{
case DateTimeKind.Unspecified:
case DateTimeKind.Local:
// +"zzzz";
TimeSpan ts = TimeZone.CurrentTimeZone.GetUtcOffset(value.ToLocalTime());
if (ts.Ticks < 0)
{
writer.WriteString("-");
}
else
{
writer.WriteString("+");
}
int hours = Math.Abs(ts.Hours);
writer.WriteString((hours < 10) ? "0" + hours : hours.ToString(CultureInfo.InvariantCulture));
int minutes = Math.Abs(ts.Minutes);
writer.WriteString((minutes < 10) ? "0" + minutes : minutes.ToString(CultureInfo.InvariantCulture));
break;
case DateTimeKind.Utc:
break;
}
writer.WriteString(JsonGlobals.DateTimeEndGuardReader);
}

我已经在我的机器上运行了以下测试

var jsonSerializer = new DataContractJsonSerializer(typeof(DateTime));
var date = DateTime.UtcNow;
Console.WriteLine("original date = " + date.ToString("s"));
using (var stream = new MemoryStream())
{
jsonSerializer.WriteObject(stream, date);

stream.Position = 0;
var deserializedDate = (DateTime)jsonSerializer.ReadObject(stream);
Console.WriteLine("deserialized date = " + deserializedDate.ToString("s"));

}

产生预期的输出:

original date = 2011-04-19T10:24:39
deserialized date = 2011-04-19T10:24:39

因此在某些时候您的日期必须是未指定的或本地的。

将其从数据库中取出后,通过调用将类型从 Unspecified 转换为 Utc

 entity.Date = DateTime.SpecifyKind(entity.Date, DateTimeKind.Utc);

并且不要忘记像我一样将 SpecifyKind 的返回值分配回您的对象

关于c# - DataContractJsonSerializer DateTime 隐式时区转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5675776/

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