les*_*ode 12 .net datetime xml-serialization
好的,我在这里错过了什么?MSDN对DateTimeSerializationMode说以下内容:
在.Net Framework的2.0及更高版本中,将此属性设置为RoundtripDateTime,以检查它们是在本地,UTC还是未指定的时区,并以保持此信息的方式进行序列化.这是默认行为,建议用于所有不与旧版本框架通信的新应用程序.
然而:
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
因此,对于定义为"date"而不是"dateTime"的XSD元素,日期不会序列化为UTC.这是一个问题,因为如果我反序列化这个XML,结果日期将是未指定的类型,以及任何到UTC的转换(实际上应该是无操作,因为在往返期间应该保留日期的UTC-ness ),至少会改变一天中的时间,有可能在昨天做出约会,这取决于你是在格林威治的东部还是西部.
不应该将日期写成:
<Date>2009-08-18Z</Date>
Run Code Online (Sandbox Code Playgroud)
?
实际上,如果我反序列化包含上述内容的文档,我会得到一个已经转换为本地时间的DateTime(我在纽约,所以那是8月17日20:00),如果我立即将该对象序列化回XML,我明白了:
<Date>2009-08-17</Date>
Run Code Online (Sandbox Code Playgroud)
因此,UTC在进入的过程中被转换为Local,并且该Local的时间部分在出路时掉线,这将使其在返回途中未指定.我们已经失去了对8月18日原始UTC日期规范的所有了解.
以下是W3C对xsd:date的说法:
[定义:]日期的值空间由dateTime时间轴上的正好一天的开顶间隔组成,从每天的开始时刻(每个时区)开始,即'00:00:00 ',但不包括'24:00:00'(与第二天的'00:00:00'相同).对于非时间化值,顶部开放区间不连续地覆盖非时间化时间线,每天一个.对于时间值,间隔从每分钟开始,因此重叠.
根本问题是,如果我执行以下操作:
或者以下内容:
这些程序中的任何一个都应该让我与我投入的日期相同.
解决方法
到目前为止我能看到的唯一方法是获得我期望的往返行为,假设所有xsd:date元素都代表UTC,实现Date属性如下:
[XmlElement(DataType = "date")]
public DateTime Date {
get { return _dt; }
set { _dt = value.Kind == DateTimeKind.Unspecified ?
DateTime.SpecifyKind(value, DateTimeKind.Utc) :
value.ToUniversalTime(); }
}
Run Code Online (Sandbox Code Playgroud)
我打开了一个Connect问题并从微软那里得到了回复,证实了我的担忧:
我们在处理Date,Time和DateTime值时有不同的行为.对于DateTime值,如果XmlDateTimeSerializationMode不是Local,则保留有关类型(UTC,Local或Unspecified)的信息.反序列化时也是如此.但是,对于日期和时间,它们总是以相同的格式序列化:(对于日期为yyyy-MM-dd,对于时间为HH:mm:ss.fffffff.zzzzzz).因此,序列化和反序列化会丢失有关种类的信息.我们正在打开文档错误,以便改进有关此文档的文档.
归档时间: |
|
查看次数: |
8947 次 |
最近记录: |