2011-10-16 29 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'類添加了一個工作示例,它保留了原始時區偏移量。請檢查一下。 –