微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

DataContractJsonSerializer DateTime隐式时区转换

如何解决DataContractJsonSerializer DateTime隐式时区转换

|| 我在数据库中有一个日期时间,然后使用Entity Framework从数据库中检索它,然后通过JSON API通过DataContractJsonSerializer传递数据。 在DataContractJsonSerializer中处理时,日期时间字段中的时间似乎已根据服务器的本地时区进行了调整。纪元表示的时间比预期的时间早1小时。 DateTime类型为UTC,但以前未指定,因此我遇到了同样的问题。 在我的应用程序中,我希望在时区之间进行显式转换,并在客户端而不是服务器上进行转换,因为这样做更有意义。我对这种隐式功能感到惊讶,因为我的datetime值应该像整数一样是简单值。 谢谢     

解决方法

如果您的DateTime.Kind等于Local或Unspecified,则
DataContractJsonSerializer
将输出时区部分(+ zzzz)。此行为不同于XmlSerializer,后者仅在Kind等于Unspecified时才输出时区部分。 如果好奇的话,请查看包含以下方法的ѭ1的源:
 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
的返回值分配回您的对象中     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。