Разбор TeamCity (Java?) - сгенерированной метки времени в .NET? - PullRequest
7 голосов
/ 04 августа 2010

Я пытаюсь интегрироваться с TeamCity REST API.Он содержит метки времени вида 20100804T104413+0100.Это почти ISO 8601, но не содержит дефисов.

Как мне преобразовать это из string в DateTime в .NET?Я пробовал:

DateTime.ParseExact(s, "yyyyMMddTHHmmss+zzzz", CultureInfo.InvariantCulture);

(и без + zzzz), но я получаю String was not recognized as a valid DateTime.

Ответы [ 3 ]

9 голосов
/ 04 августа 2010

Это работает для меня:

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».

Обратите внимание, что если вы переформатируете его, используя тот же формат, вы закончитевверх с ":" в середине спецификатора смещения: (

4 голосов
/ 04 августа 2010

Я знаю вопрос.ответ уже получен, но я полагаю, что есть несколько примечаний, если можно:

Проблемы с использованием DateTime

Я бы посоветовал не использовать 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

Эта проблема исчезнет, ​​если вы вместо этого будете использовать 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(":", "");
2 голосов
/ 15 января 2015

Это немного не по теме в этом старом посте, но так как я нашел пост, когда гуглил для разбора дат Teamcity api, вот версия Javascript для всех, кто интересуется тем же:

moment("20150107T085108+0100", 'YYYYMMDDTHHmmssZ').format('YYYY-MM-DD HH:mm:ss')

Он использует превосходную библиотеку Moment.js для анализа.

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