DateTime отформатирован в ISO 8601 в UT C (с суффиксом «Z»). Синтаксический анализ в режиме Roundtrip (DateTime.Parse("...", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind)
) автоматически обработает его правильно:
Строки, которые передаются в методы Parse, TryParse, ParseExact и TryParseExact DateTime и DateTimeOffset может быть проанализирован с помощью спецификатора формата «O» или «o», если они находятся в одном из этих форматов. В случае объектов DateTime перегрузка синтаксического анализа, которую вы вызываете, должна также включать параметр styles со значением DateTimeStyles.RoundtripKind. Обратите внимание, что если вы вызовете метод синтаксического анализа со строкой пользовательского формата, которая соответствует спецификатору формата "O" или "o", вы не получите те же результаты, что и "O" или "o". Это связано с тем, что методы синтаксического анализа, использующие строку нестандартного формата, не могут анализировать строковое представление значений даты и времени, в которых отсутствует компонент часового пояса, или использовать «Z» для обозначения UT C. [мой акцент]
Что не так в коде: указав «Z» в качестве символа в строке формата, вы буквально сопоставляете символ «Z» (заглавная «Z» не является спецификатором пользовательского формата), что приводит к выбрасыванию информации о часовом поясе и в зависимости от параметра DateTimeStyles для интерпретации часового пояса. Можно выбрать правильное значение для этого, но лучшим вариантом является использование режима формата туда-обратно, который уже знает, как позаботиться об этом.
Редактировать: досадно, DateTime.ParseExact( datestr, "o", CultureInfo.InvariantCulture )
(синтаксический анализ с " o ") не работает, но анализ с параметром DateTimeStyles.RoundtripKind работает. Спасибо @SirRufo за указание на это.