Разбор Twitter, созданного на дату в формате UTC

Я понимаю, что есть много тем о разборе дат твиттера, но у меня особая проблема, и я не смог найти никаких тем, относящихся к этому.

Я получаю это сообщение: https://twitter.com/bodegamcallen/status/1033757489567805440

дата создания которого - 26.08.2018 в 9:46 Central Time.

Дата создания в API следующая: «Вс, 26 августа, 16:46:06 +0000 2018».

Это имеет смысл, поскольку 16:46 (14:46) UTC - это 9:46 AM по центральному времени (-500).

Однако я разбираю это с помощью этого кода:

statusModel.DatePosted = DateTime.ParseExact(
    this.created_at, "ddd MMM dd HH:mm:ss zzzz yyyy", 
    CultureInfo.InvariantCulture.DateTimeFormat, DateTimeStyles.AssumeUniversal);

и вместо того, чтобы получить желаемое время UTC, показанное выше, я получаю это: 26.08.2018 16:46:06

Если я изменю DateTimeStyle на None или AssumeLocal, я получу следующее: 26.08.2018 11:46:06

Ни то, ни другое не правильно!

Я пробовал разные форматы из других потоков, например:

  • "ддд МММ дд ЧЧ: мм: сс К гггг"
  • "ддд МММ дд ЧЧ: мм: сс З гггг"
  • "ддд МММ дд ЧЧ: мм: сс zzz гггг"
  • "ддд МММ дд ЧЧ: мм: сс + ffff гггг"

Я также попытался использовать DateTimeOffset.Parse и изменить культуру на мою (en-us)

все они дают мне одинаковые результаты.

Что я делаю не так? Как сделать так, чтобы дата и время совпадали со временем в формате UTC и значением даты, которое я получаю от API?

🤔 А знаете ли вы, что...
C# обладает сборщиком мусора, который автоматически управляет памятью, что снижает риск утечек памяти.


1
585
2

Ответы:

Ага! Оказалось, что настройки моей учетной записи Twitter были настроены на тихоокеанское время, а не на центральное время, и это объясняет разницу в два часа.

Я изменил настройки часового пояса для своей учетной записи, как описано здесь: https://help.twitter.com/en/managing-your-account/how-to-change-time-zone-settings

А после перехода на центральное время данные API поступают правильно!

надеюсь, что это поможет кому-то другому. Часовые пояса, амирит?


Несколько вещей:

  • zzzz не является допустимым спецификатором. Всегда проверяйте эти документы, если сомневаетесь.
  • K - единственный спецификатор часового пояса, который подходит для синтаксического анализа DateTime. Остальные (z, zz и zzz) предназначены для синтаксического анализа DateTimeOffset.
  • Когда во входной строке есть смещение любой или информация о часовом поясе (даже если это +0000 или Z), DateTime.Parse и DateTime.ParseExact по умолчанию предполагают, что вы хотите, чтобы тип вывода был DateTimeKind.Local, и что вы хотите, чтобы значение было скорректировано на локальное, независимо от того, что это во входной строке. Изучите выходной .Kind, если вы не уверены, что он работает правильно. Если вы хотите вместо этого использовать UTC, вы должны передать DateTimeStyles.AdjustToUniversal.
  • Вам не нужно передавать DateTimeStyles.AssumeUniversal, потому что во входной строке присутствует информация о часовом поясе.
  • Это не недействительно, но вам не нужно проходить CultureInfo.InvariantCulture.DateTimeFormat. Достаточно и чаще всего пройти CultureInfo.InvariantCulture.

Собирая все это вместе, ваш код должен быть:

statusModel.DatePosted = DateTime.ParseExact(
    this.created_at, "ddd MMM dd HH:mm:ss K yyyy", 
    CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal);

И, конечно же, вы избавите себя от лишних хлопот и путаницы, если замените свой DatePosted на тип DateTimeOffset. Это лучше для такого рода сценариев, и тогда вам не нужно беспокоиться о DateTimeKind или DateTimeStyles.