DateTime в ISO 8601 в C#: полное руководство с ответами на частые вопросы

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Как превратить DateTime в строку ISO 8601 на C#? Проблема, которая мучает даже опытных

Вы когда-нибудь сталкивались с ситуацией, когда ваш API возвращает дату в формате "2023-01-15T10:30:00", а клиент её не понимает? Или, наоборот, вы получаете дату из внешнего сервиса, а она выглядит как "2023-01-15T10:30:00+03:00", и ваш парсер ломается? Знакомо? Если вы работаете с C# и объектом DateTime, то вопрос получения ISO 8601 строки — это классика. На Stack Overflow этот вопрос набрал тысячи просмотров, и не зря. Сегодня мы раз и навсегда разберёмся, как правильно преобразовать DateTime в строку формата ISO 8601, избежав типичных граблей.

Мы не просто покажем пару строк кода. Мы разберём C# DateTime формат для ISO 8601, рассмотрим работу с часовыми поясами, миллисекундами и ответим на самые частые вопросы. Поехали!

Что такое ISO 8601 и почему это важно?

ISO 8601 — это международный стандарт представления даты и времени. Он выглядит так: 2023-12-25T14:30:00.0000000+03:00. Ключевые особенности:

  • Разделитель T между датой и временем.
  • Часовой пояс указывается в конце (Z для UTC или смещение вида +05:00).
  • Дробная часть секунд (миллисекунды, тики).

Зачем это нужно? JSON, XML, REST API, базы данных — везде, где нужна однозначная передача момента во времени, без привязки к локальной культуре сервера. Неправильный формат — и ваш парсер на другой стороне может отбросить часы или перепутать день с месяцем. Поэтому формат даты ISO 8601 C# — это must-have навык для любого бэкенд-разработчика.

Самый простой способ: DateTime.ToString() с форматом "o"

В C# есть встроенный спецификатор формата для круглосуточного (round-trip) формата — это буква "o" (строчная). Он даёт полную строку ISO 8601 с максимальной точностью.

DateTime now = DateTime.Now;
string isoString = now.ToString("o");
Console.WriteLine(isoString);
// Пример вывода: 2023-12-25T14:30:00.1234567+03:00

Это самый простой способ получить ISO 8601 строку C#. Но есть нюанс: если ваш DateTime имеет Kind = Unspecified, то в конце строки не будет указания часового пояса. Это может быть проблемой для строгих парсеров. Решение — всегда использовать DateTimeOffset или явно задавать Kind.

Как получить ISO 8601 без миллисекунд?

Иногда миллисекунды (или даже тики) не нужны. Например, для логов или простых дат. Используйте кастомный формат:

DateTime now = DateTime.UtcNow;
string isoShort = now.ToString("yyyy-MM-ddTHH:mm:ssK");
Console.WriteLine(isoShort);
// Пример: 2023-12-25T14:30:00Z

Здесь K — это спецификатор часового пояса. Для UTC он даёт Z, для локального времени — смещение.

Проблема с часовыми поясами: DateTime vs DateTimeOffset

Главная боль разработчиков — это путаница между DateTime и DateTimeOffset. Если вы хотите получить ISO 8601 дата C#, которая будет однозначно интерпретирована в любой точке мира, используйте DateTimeOffset. Он всегда содержит смещение от UTC.

DateTimeOffset nowOffset = DateTimeOffset.Now;
string isoOffset = nowOffset.ToString("o");
Console.WriteLine(isoOffset);
// Пример: 2023-12-25T14:30:00.1234567+03:00

Если же вы работаете с DateTime, всегда проверяйте его свойство Kind:

  • DateTimeKind.Utc — даёт Z в конце.
  • DateTimeKind.Local — даёт локальное смещение (например, +03:00).
  • DateTimeKind.Unspecified — не даёт ничего! Это частая причина ошибок.

Как исправить для DateTime с Kind.Unspecified? Преобразуйте его в DateTimeOffset с явным указанием смещения:

DateTime unspecifiedDate = new DateTime(2023, 12, 25, 14, 30, 0);
DateTimeOffset withOffset = new DateTimeOffset(unspecifiedDate, TimeSpan.FromHours(3));
string iso = withOffset.ToString("o");
Console.WriteLine(iso);
// 2023-12-25T14:30:00.0000000+03:00

Частые вопросы (из реального опыта Stack Overflow)

1. Как получить ISO 8601 строку для UTC?

Проще всего использовать DateTime.UtcNow и формат "o":

string utcIso = DateTime.UtcNow.ToString("o");
// 2023-12-25T11:30:00.1234567Z

2. Как обрезать миллисекунды, но оставить часовой пояс?

Используйте кастомный формат без дробной части:

string noMs = DateTimeOffset.Now.ToString("yyyy-MM-ddTHH:mm:sszzz");
// 2023-12-25T14:30:00+03:00

Обратите внимание: zzz — это смещение в формате +HH:mm.

3. Как распарсить ISO 8601 обратно в DateTime?

Используйте DateTime.Parse или DateTimeOffset.Parse:

string isoInput = "2023-12-25T14:30:00.1234567+03:00";
DateTimeOffset parsed = DateTimeOffset.Parse(isoInput);
Console.WriteLine(parsed); // 25.12.2023 14:30:00 +03:00

4. Что делать, если в строке нет часового пояса, но я знаю, что это UTC?

Используйте DateTimeStyles.AssumeUniversal:

string noTimeZone = "2023-12-25T14:30:00";
DateTime utcDate = DateTime.Parse(noTimeZone, null, DateTimeStyles.AssumeUniversal);
Console.WriteLine(utcDate.Kind); // Utc

Продвинутые техники: работа с точностью и культурами

Иногда нужно получить ISO 8601 строку C# с определённым количеством знаков после запятой. Например, 3 знака (миллисекунды):

DateTime now = DateTime.UtcNow;
string customPrecision = now.ToString("yyyy-MM-ddTHH:mm:ss.fffK");
Console.WriteLine(customPrecision);
// 2023-12-                

Блоги

Рекомендаций по книгам