2011-10-16 28 views
3

我遇到XmlConvertDateTime问题。`XmlConvert.ToDateTime(String)`和`XmlConvert.ToString(DateTime)`输出不一致

当转换某些字符串XmlConvert.ToDateTime(String)再转换与XmlConvert.ToString(DateTime)导致DateTime返回字符串,结果字符串是从原始字符串不同,这取决于当地的时区。

下面的控制台应用程序的代码演示该问题:

using System; 
using System.Xml; 

namespace DateTimeXmlConvertTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Console.WriteLine("Original Value\t\t\t\tNew Value"); 
      Console.WriteLine("--------------\t\t\t\t---------"); 

      for (int i = -12; i <= 12; i++) 
      { 
       string sign = i < 0 ? "" : "+"; 

       string originalString = "2011-10-01T01:18:54.6652000" + sign + i.ToString("D2") + ":00"; 
       DateTime now = XmlConvert.ToDateTime(originalString); 
       string newValue = XmlConvert.ToString(now); 
       Console.WriteLine(originalString + "\t" + newValue); 
      } 
     } 
    } 
} 

在我的电脑上运行这个程序(Windows 7的64位,时区UTC + 02:00日光),我有以下的输出:

Original Value       New Value 
--------------       --------- 
2011-10-01T01:18:54.6652000-12:00  2011-10-01T16:18:54.6652000+03:00 
2011-10-01T01:18:54.6652000-11:00  2011-10-01T15:18:54.6652000+03:00 
2011-10-01T01:18:54.6652000-10:00  2011-10-01T14:18:54.6652000+03:00 
2011-10-01T01:18:54.6652000-09:00  2011-10-01T13:18:54.6652000+03:00 
2011-10-01T01:18:54.6652000-08:00  2011-10-01T12:18:54.6652000+03:00 
2011-10-01T01:18:54.6652000-07:00  2011-10-01T11:18:54.6652000+03:00 
2011-10-01T01:18:54.6652000-06:00  2011-10-01T10:18:54.6652000+03:00 
2011-10-01T01:18:54.6652000-05:00  2011-10-01T09:18:54.6652000+03:00 
2011-10-01T01:18:54.6652000-04:00  2011-10-01T08:18:54.6652000+03:00 
2011-10-01T01:18:54.6652000-03:00  2011-10-01T07:18:54.6652000+03:00 
2011-10-01T01:18:54.6652000-02:00  2011-10-01T06:18:54.6652000+03:00 
2011-10-01T01:18:54.6652000-01:00  2011-10-01T05:18:54.6652000+03:00 
2011-10-01T01:18:54.6652000+00:00  2011-10-01T04:18:54.6652000+03:00 
2011-10-01T01:18:54.6652000+01:00  2011-10-01T03:18:54.6652000+03:00 
2011-10-01T01:18:54.6652000+02:00  2011-10-01T02:18:54.6652000+03:00 
2011-10-01T01:18:54.6652000+03:00  2011-10-01T01:18:54.6652000+03:00 
2011-10-01T01:18:54.6652000+04:00  2011-10-01T00:18:54.6652000+03:00 
2011-10-01T01:18:54.6652000+05:00  2011-09-30T23:18:54.6652000+03:00 
2011-10-01T01:18:54.6652000+06:00  2011-09-30T22:18:54.6652000+03:00 
2011-10-01T01:18:54.6652000+07:00  2011-09-30T21:18:54.6652000+03:00 
2011-10-01T01:18:54.6652000+08:00  2011-09-30T20:18:54.6652000+03:00 
2011-10-01T01:18:54.6652000+09:00  2011-09-30T19:18:54.6652000+03:00 
2011-10-01T01:18:54.6652000+10:00  2011-09-30T18:18:54.6652000+03:00 
2011-10-01T01:18:54.6652000+11:00  2011-09-30T17:18:54.6652000+03:00 
2011-10-01T01:18:54.6652000+12:00  2011-09-30T16:18:54.6652000+03:00 

转换为,然后从不同的字符串得到结果的可能性如何?

在这种情况下有没有办法让它输出原始字符串?

谢谢。

+1

你会期待什么?你在不同的时区有不同的'DateTime'实例。使用这些方法的目标是拥有一个时区,因此它们是一致的。如果您希望能够取回时间,则需要跟踪时区。 –

+0

我期待'ToString()'创建完全相同的字符串,由'(ToDateTime()')创建的'DateTime'的实例。使用这些方法的目标是将xml dateTime格式转换为xml,并且不修改/计算时区,只需使用与“DateTime”实例中相同的时区即可。 – DxCK

+0

请看看我的答案。您正在使用过时的方法,无法控制时区的解释方式。 –

回答

4

首先,XmlConvert.ToDateTime(String)过载为陈旧。该文件明确指出您应该使用XmlConvert.ToDateTime(String, XmlDateTimeSerializationMode)代替。有了它,你可以指定XmlDateTimeSerializationMode,这是记录如下:

一个指定的日期是否应转换为本地时间或保留为协调世界时(UTC)的XmlDateTimeSerializationMode值的,如果它是UTC日期。

当你有一个DateTime的实例时,它是如何构建的(例如它的时区)将会丢失。时区将从原始字符串中正确解析并转换为UTC或本地时间,但是从中转换而来的时区将在此过程中丢失。

如果要保留时区偏移量,请使用DateTimeOffset类。它的行为与DateTime类似,但保留了创建它的时区偏移量。 XmlConvert有一个ToDateTimeOffset方法,它完全符合你的要求。这里有一个工作示例:

Console.WriteLine("{0,33}\t{1,33}", "Original Value", "New Value"); 
Console.WriteLine("{0}\t{0}", new String('-', 33)); 

for (int i = -12; i <= 12; i++) 
{ 
    string sign = i < 0 ? "" : "+"; 
    string originalString = String.Format(
     "2011-10-01T01:18:54.6652123{0}{1:D2}:00", sign, i); 
    DateTimeOffset dateTime = XmlConvert.ToDateTimeOffset(originalString); 
    string newString = XmlConvert.ToString(dateTime); 
    Console.WriteLine("{0}\t{1}", originalString, newString); 
} 

你现在唯一的问题是,+00:00将被序列化到Z,可如果你自己格式化newString避免的,就像这样:

string newString = String.Format("{0:yyyy-MM-ddTHH:mm:ss.fffffffzzz}", dateTime); 
+0

我尝试了所有其他重载,并且没有超载解决不同输出字符串的问题。 – DxCK

+0

@DxCK,我使用'DateTimeOffset'类添加了一个工作示例,它保留了原始时区偏移量。请检查一下。 –