Я пытаюсь интегрироваться с TeamCity REST API. Это содержит метки времени формы 20100804T104413+0100
. Это - почти ISO 8601, но не содержит дефисы.
Как я преобразовываю это из a string
к a DateTime
в.NET? Я попробовал:
DateTime.ParseExact(s, "yyyyMMddTHHmmss+zzzz", CultureInfo.InvariantCulture);
(и без +zzzz), но я добираюсь String was not recognized as a valid DateTime.
У меня это работает:
using System;
using System.Globalization;
class Test
{
static void Main()
{
string text = "20100804T104413+0100";
DateTime dt = DateTime.ParseExact
(text,
"yyyyMMdd'T'HHmmsszzz",
CultureInfo.InvariantCulture);
Console.WriteLine(dt);
}
}
На самом деле вам не нужны кавычки вокруг буквы «Т», но я стараюсь вставить их, чтобы сделать шаблон более понятным. Точно так же «zzz» может быть «zzzz» - но я думаю, проблема была в «+», который был у вас до «zzz».
Обратите внимание, что если вы переформатируете его, используя тот же формат, вы получите ":" в середине спецификатора смещения: (
Я знаю вопрос. уже ответил, но я считаю, что есть несколько примечаний, если можно:
Я бы посоветовал не использовать DateTime в вашем сценарии, поскольку кажется вероятным, что вы хотите, чтобы представление было равным при обратном преобразовании (т. е. при обратном преобразовании в строку представление должно быть равным). Проблема с DateTime в том, что он не сохраняет точную информацию о часовом поясе.
Предлагаемое решение позволяет изменять информацию о часовом поясе. Это зависит от ввода, но, используя инвариантный язык и региональные параметры, вы получите объект DateTime {4-8-2010 11:44:13}
. Я думал, что это можно исправить, используя DateTimeStyles.RoundtripKind
, как в следующем примере, но, учитывая, что в DateTime
нет информации о часовом поясе, это все равно не сработает:
// DON'T DO THIS, dangerous code ahead:
DateTime time = DateTime.ParseExact(
"20100804T104413+0100",
"yyyyMMdd'T'HHmmssK",
CultureInfo.InvariantCulture,
DateTimeStyles.RoundtripKind);
// loosing data when converting back:
string convertedBack = time.ToString("yyyyMMdd'T'HHmmssK");
// convertedBack now contains "20100804T114413+02:00"
Эта проблема исчезнет, если вы вместо этого используете DateTimeOffset
для своих задач. Идея остается той же, но внезапно срабатывает обратный обмен:
// DO THIS instead:
DateTimeOffset parsedDate = DateTimeOffset.ParseExact(
"20100804T104413+0100",
"yyyyMMdd'T'HHmmsszzz",
CultureInfo.InvariantCulture,
DateTimeStyles.RoundtripKind);
// converting back is now easy:
convertedBack = parsedDate.ToString("yyyyMMdd'T'HHmmssK");
// convertedBack contains the string "20100804T104413+01:00"
Конечно, важна ли информация о часовом поясе от вашей ситуации. Но это будет не первый раз, когда 10 часов изменится на 11, и тогда найти ошибку может быть сложно.
Как упоминал Джон Скит, в вашем выводе есть двоеточие «:», которого не было на входе. Таким образом, полный обход кажется невозможным. К сожалению, в то время как DateTimeFormatInfo
в любой культуре можно изменить для изменения почти каждого внешнего вида, то есть вы можете установить TimeSeparator
в пустую строку, и двоеточия исчезают в форматированных временах, этот уровень детализации недоступен в смещении часового пояса. Хуже того, Reflector показывает, что он намеренно жестко запрограммирован (однажды у меня была такая же проблема с удалением «+» для положительных смещений):
if (offset >= TimeSpan.Zero)
{
result.Append('+');
}
else
{
result.Append('-');
offset = offset.Negate();
}
result.AppendFormat(CultureInfo.InvariantCulture, "{0:00}:{1:00}", new object[] { offset.Hours, offset.Minutes });
Решение состоит в том, чтобы либо предоставить свой собственный IFormatProvider
, либо чтобы быть прагматичным, просто удалите двоеточие:
convertedBack = parsedDate.ToString("yyyyMMdd'T'HHmmssK").Replace(":", "");