DateTime和xsd:date的往返XML序列化? [英] Roundtrip XML Serialization of DateTime and xsd:date?

查看:131
本文介绍了DateTime和xsd:date的往返XML序列化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,我在这里想念什么? MSDN关于DateTimeSerializationMode说以下内容:

OK, what am I missing here? MSDN says the following with regard to DateTimeSerializationMode:


在2.0版和更高版本的.Net
Framework中,设置了此属性到
的RoundtripDateTime对象将被检查
以确定它们是否在
当地,UTC或未指定的时间
区域中,并以
这样的方式进行序列化信息被保留。
这是默认行为,建议所有不与框架旧
版本通信的新应用程序
使用

In versions 2.0 and later of the .Net Framework, with this property set to RoundtripDateTime objects are examined to determine whether they are in the local, UTC or an unspecified time zone, and are serialized in such a way that this information is preserved. This is the default behavior and is recommended for all new applications that do not communicate with older versions of the framework.

但是:

namespace ConsoleApplication1 {
    public class DateSerTest {
        [XmlElement(DataType = "date")]
        public DateTime Date { get; set; }
    }

    class Program {
        static void Main(string[] args) {
            DateSerTest d = new DateSerTest { 
                Date = DateTime.SpecifyKind(new DateTime(2009,8,18), DateTimeKind.Utc),
            };
            XmlSerializer ser = new XmlSerializer(typeof(DateSerTest));
            using (FileStream fs = new FileStream("out.xml", FileMode.Create)) {
                ser.Serialize(fs, d);
            }

            // out.xml will contain:
            // <Date>2009-08-18</Date>

            using (FileStream fs = new FileStream("out.xml", FileMode.Open)) {
                DateSerTest d1 = (DateSerTest) ser.Deserialize(fs);
                Console.WriteLine(d1.Date); // yields: 8/18/2009 12:00:00 AM
                Console.WriteLine(d1.Date.Kind); // yields: Unspecified
            }

            // in.xml:
            // <DateSerTest>
            //     <Date>2009-08-18Z</Date>
            // </DateSerTest>

            using (FileStream fs = new FileStream("in.xml", FileMode.Open)) {
                DateSerTest d1 = (DateSerTest) ser.Deserialize(fs);
                Console.WriteLine(d1.Date); // yields: 8/17/2009 8:00:00 PM
                Console.WriteLine(d1.Date.Kind); // yields: Local
                using (FileStream fs1 = new FileStream("out2.xml", FileMode.Create)) {
                    ser.Serialize(fs1, d1);

                    // out2.xml will contain:
                    // <Date>2009-08-17</Date>
                }
            }
            Console.ReadKey();
        }
    }
}

因此对于XSD元素定义为日期而不是 dateTime,该日期未序列化为UTC。这是一个问题,因为如果我反序列化此XML,则结果日期将是未指定的,并且任何对UTC的转换(实际上应该是空操作,因为在往返过程中应保留该日期的UTC时间),至少会在一天中的某个时间更改,并有50%的机会在昨天定日期,具体取决于您是格林威治东部还是西部。

So for XSD elements defined as "date" rather than "dateTime", the date is not serialized as UTC. This is a problem, because if I deserialize this XML the resulting date will be of Kind Unspecified, and any conversion to UTC (which should in fact be a no-op because the UTC-ness of the date should have been preserved during the roundtrip), will change at least the time of day, with a 50% chance of making the date yesterday, depending on whether you're east or west of Greenwich.

应该日期写为:

  <Date>2009-08-18Z</Date>

确实,如果我反序列化包含上述内容的文档,我得到的DateTime已经转换为本地时间(我在纽约,所以是8月17日20:00),如果我立即将该对象序列化为XML,我将得到:

Indeed, if I deserialize a document that contains the above, I get a DateTime that's already been converted to Local time (I'm in New York so that's Aug 17th 20:00), and if I immediately serialize that object back to XML, I get:

  <Date>2009-08-17</Date>

因此,UTC在进入时转换为Local,而该Local的时间部分在出路,这将使其在返回时再次变为未指定。我们已经对8月18日的原始UTC日期规范一无所知。

So, UTC was converted to Local on the way in, and the time part of that Local dropped on the way out, which will make it Unspecified on the way back in again. We've lost all knowledge of the original UTC date specification of August 18th.

W3C所说的xsd:date:

Here's what the W3C says about xsd:date:


[定义:]
日期的[值空间]由
的开盘时间间隔组成,恰好是
上一天的长度dateTime的时间轴,从
每天的开始时刻开始(在每个时区的
中),即'00:00:00',直到
但不包括'24:00:00 (与下一个
日的 00:00:00相同)。对于非时区的值,
的顶部开放时间间隔不相交地覆盖了非时区的时间轴中的
,即每
天一个。对于时区值,
间隔从每分钟开始,因此
重叠。

[Definition:] The ·value space· of date consists of top-open intervals of exactly one day in length on the timelines of dateTime, beginning on the beginning moment of each day (in each timezone), i.e. '00:00:00', up to but not including '24:00:00' (which is identical with '00:00:00' of the next day). For nontimezoned values, the top-open intervals disjointly cover the nontimezoned timeline, one per day. For timezoned values, the intervals begin at every minute and therefore overlap.

基本问题是如果我执行以下操作:

The fundamental problem is that if I do the following:


  1. 构造(或以其他方式接收)UTC DateTime值。

  2. 使用定义该字段为xsd:date

  3. 的模式将其序列化为XML。将XML反序列化为DateTime。

  4. 将DateTime转换为UTC(应该没有任何作用,因为往返应该保留了这一点。)

  1. Construct (or otherwise receive) a UTC DateTime value.
  2. Serialize to XML with a schema defining that field as xsd:date
  3. Deserialize that XML back to a DateTime.
  4. Convert the DateTime to UTC (which should have no effect since the "roundtrip" should have preserved this).

或以下内容:


  1. 反序列化包含UTC xsd:date对象的XML文档(例如2009-08-18Z)。

  2. 将其序列化回

这两个过程中的任何一个都应该让我与输入的日期相同。

Either of these procedures should get me the same date I put in.

解决方法

到目前为止,我唯一能看到的获得往返行程的方法

The only way I can see so far to get the roundtrip behaviour I expect is to implement the Date property as follows, on the assumption that all xsd:date elements represent UTC:

[XmlElement(DataType = "date")]
public DateTime Date {
    get { return _dt; }
    set { _dt = value.Kind == DateTimeKind.Unspecified ? 
                    DateTime.SpecifyKind(value, DateTimeKind.Utc) : 
                    value.ToUniversalTime(); }
}


推荐答案

我打开了一个Connect问题并从微软那里得到了回报,证实了我的担心:

I opened a Connect issue and got this back from Microsoft, confirming my fears:


我们对
处理Date,Time和DateTime $ b有不同的行为$ b值。对于DateTime值,如果
XmlDateTimeSerializationMode不是
Local,则保留有关
类型(UTC,本地或未指定)的信息。
反序列化时也是如此。但是,对于Date和
Time,它们总是以相同的格式序列化
:(yyyy-MM-dd为
Date,HH:mm:ss.fffffff.zzzzzz为
时间)。因此,有关
种类的信息会在序列化和
反序列化时丢失。我们正在为自己打开一个
文档错误,以便改善
的文档质量。

We have different behaviors for handling Date, Time and DateTime values. For DateTime values, if XmlDateTimeSerializationMode is not Local the information about the kind (UTC, Local or Unspecified) is preserved. This is also true while deserializing. However, for Date and Time, they are always serialized out with the same format: (yyyy-MM-dd for Date and HH:mm:ss.fffffff.zzzzzz for Time). So the information about kind is lost on serializing and deserializing. We are opening a documentation bug on our side in order to improve the documentation about this.

这篇关于DateTime和xsd:date的往返XML序列化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆