Выводы `XmlConvert.ToDateTime (String)` и `XmlConvert.ToString (DateTime)` противоречивы - PullRequest
3 голосов
/ 17 октября 2011

У меня проблемы с XmlConvert и DateTime.

При преобразовании некоторой строки с XmlConvert.ToDateTime(String) затем преобразовать полученный DateTime обратно в строку с XmlConvert.ToString(DateTime), и полученная строка отличается от исходной строки и зависит от локальной TimeZone.

Следующий код консольного приложения, демонстрирующий проблему:

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 x64, TimeZone 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

Как это возможно при преобразовании, а затем в результате с другой строкой?

Есть ли способ заставить его выводить исходную строку в этом случае?

Спасибо.

Ответы [ 2 ]

4 голосов
/ 17 октября 2011

Во-первых, перегрузка XmlConvert.ToDateTime(String) равна устарела . В документации четко указано, что вы должны использовать XmlConvert.ToDateTime(String, XmlDateTimeSerializationMode). С его помощью вы можете указать XmlDateTimeSerializationMode, который задокументирован следующим образом:

Одно из значений XmlDateTimeSerializationMode, которое указывает, следует ли преобразовывать дату в местное время или сохранять ее как всемирное координированное время (UTC), если это дата в формате 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);
1 голос
/ 11 июля 2014

А как насчет XmlConvert.ToDateTime (String, XmlDateTimeSerializationMode) , а для сохранения смещения часового пояса используйте параметр:

System.Xml.XmlDateTimeSerializationMode.RoundtripKind

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...