Бөлісу құралы:


Анализ строк даты и времени в .NET

.NET предоставляет несколько типов для работы с данными даты и времени, оптимизированными для различных сценариев:

  • DateTime — представляет дату и время вместе, идеально подходит для обоих компонентов или при работе с устаревшим кодом.
  • DateOnly (недоступно в .NET Framework) — представляет только дату без сведений о времени, идеально подходит для дней рождения, анниверсов или бизнес-дат.
  • TimeOnly (недоступно в .NET Framework) — представляет только время без сведений о дате, идеально подходит для расписаний, предупреждений или повторяющихся ежедневных событий.

Каждый тип предоставляет методы синтаксического анализа, преобразующие строки в соответствующие объекты, с различными уровнями гибкости и контроля над процессом синтаксического анализа.

Общие понятия синтаксического анализа

Все три типа даты и времени используют аналогичные подходы к анализу:

  • Parse и TryParse методы - Преобразуют множество распространенных строковых представлений, используя текущие или заданные региональные настройки.
  • ParseExact и TryParseExact методы — преобразование строк, соответствующих конкретным форматным шаблонам, обеспечивая точный контроль над ожидаемыми форматами, включая параметры языка и региональных настроек.
  • Строки форматирования - Определите шаблоны для синтаксического анализа, используя стандартные или пользовательские спецификаторы формата.

Разные культуры используют разные порядки для дня, месяца и года. В некоторых представлениях используется 24-часовой формат времени, а в других указывается "AM" и "PM". Методы синтаксического анализа обрабатывают эти варианты с помощью правил форматирования, зависящих от культуры.

Объект DateTimeFormatInfo предоставляет контроль над интерпретацией текста. Свойства описывают разделители даты и времени, имена месяцев, дней, эр и формат для обозначений AM и PM. Можно указать культуру через параметр IFormatProvider с помощью объекта CultureInfo или объекта DateTimeFormatInfo.

Дополнительные сведения о шаблонах форматирования см. в стандартных строках формата даты и времени и настраиваемых строках формата даты и времени.

Это важно

DateOnly и TimeOnly типы недоступны для .NET Framework.

Синтаксический анализ DateTime

DateTime представляет компоненты даты и времени вместе. При анализе строк с DateTime объектами необходимо учитывать несколько DateTimeаспектов:

  • Обработка отсутствующих сведений - DateTime использует значения по умолчанию, если части отсутствуют в входной строке.
  • Поддержка часовых поясов и смещения UTC - DateTime может представлять локальные, UTC или неопределенные часовые пояса.
  • Объединенный синтаксический анализ даты и времени — должен обрабатывать как компоненты даты, так и времени в одной операции.

Обработка отсутствующих сведений

Текст, представляющий дату или время, может пропустить некоторые сведения. Например, большинство людей предполагают, что дата "12 марта" относится к текущему году. Аналогичным образом, "Март 2018" представляет месяц марта 2018 года. Текст, представляющий время, часто включает только часы, минуты и обозначение AM/PM. DateTime Методы синтаксического анализа обрабатывают эту недостающую информацию с помощью разумных значений по умолчанию:

  • Когда присутствует только время, часть даты указывается текущей датой.
  • Если указана только дата, время по умолчанию полночь.
  • Если год не указан в дате, используется текущий год.
  • Если день месяца не указан, используется первый день месяца.

Если дата присутствует в строке, она должна включать месяц и один из дней или года. Если время присутствует, оно должно включать час, а также минуты или указатель AM/PM.

Можно указать константу NoCurrentDateDefault для переопределения этих значений по умолчанию. При использовании этой константы все отсутствующие свойства года, месяца или дня задаются значением 1. Последний пример с использованием Parse демонстрирует это поведение.

Управление смещением по времени и часовыми поясами UTC

Помимо даты и компонента времени строковое представление даты и времени может включать смещение, указывающее, сколько времени отличается от согласованного универсального времени (UTC). Например, строка "2/14/2007 5:32:00 -7:00" определяет время, которое на семь часов раньше времени UTC. Если смещение опущено из строкового представления времени, синтаксический анализ возвращает объект DateTime со свойством Kind, равным DateTimeKind.Unspecified. Если задано смещение, синтаксический анализ возвращает объект DateTime со свойством Kind, равным DateTimeKind.Local. Его значение также настраивается на локальный часовой пояс компьютера. Это поведение можно изменить с помощью значения DateTimeStyles с методом парсинга.

Неоднозначная обработка дат

Поставщик формата также используется для интерпретации неоднозначной числовой даты. Неясно, какие компоненты даты представлены строкой "02/03/04" — это месяц, день и год. Компоненты интерпретируются в соответствии с порядком аналогичных форматов дат в поставщике формата.

DateTime.Parse

В следующем примере показано использование DateTime.Parse метода для преобразования string в объект DateTime. В этом примере используется культура, связанная с текущим потоком. Если CultureInfo, связанный с текущим языком и региональными параметрами, не может проанализировать входную строку, выбрасывается FormatException.

static void DateTimeParseExample()
{
    // Parse common date and time formats using current culture
    var dateTime1 = DateTime.Parse("1/15/2025 3:30 PM");
    var dateTime2 = DateTime.Parse("January 15, 2025");
    var dateTime3 = DateTime.Parse("15:30:45");

    Console.WriteLine($"Parsed: {dateTime1}");
    Console.WriteLine($"Parsed: {dateTime2}");
    Console.WriteLine($"Parsed: {dateTime3}");

    // Parse with specific culture
    var germanDate = DateTime.Parse("15.01.2025", new CultureInfo("de-DE"));
    Console.WriteLine($"German date parsed: {germanDate}");
}
Sub DateTimeParseExample()
    ' Parse common date and time formats using current culture
    Dim dateTime1 = DateTime.Parse("1/15/2025 3:30 PM")
    Dim dateTime2 = DateTime.Parse("January 15, 2025")
    Dim dateTime3 = DateTime.Parse("15:30:45")

    Console.WriteLine($"Parsed: {dateTime1}")
    Console.WriteLine($"Parsed: {dateTime2}")
    Console.WriteLine($"Parsed: {dateTime3}")

    ' Parse with specific culture
    Dim germanDate = DateTime.Parse("15.01.2025", New CultureInfo("de-DE"))
    Console.WriteLine($"German date parsed: {germanDate}")
End Sub

Вы также можете явно определить язык и региональные параметры, соглашения о форматировании которых используются при разборе строки. Вы указываете один из стандартных объектов DateTimeFormatInfo, возвращаемых свойством CultureInfo.DateTimeFormat. В следующем примере используется поставщик формата для анализа немецкой строки в DateTime. Он создает CultureInfo, представляющий культуру de-DE. Этот объект CultureInfo гарантирует успешный синтаксический анализ конкретной этой строки. Этот процесс исключает любой параметр в CurrentCulture из CurrentThread.

static void DateTimeParseGermanExample()
{
    var cultureInfo = new CultureInfo("de-DE");
    string dateString = "12 Juni 2008";
    var dateTime = DateTime.Parse(dateString, cultureInfo);
    Console.WriteLine(dateTime);
    // The example displays the following output:
    //       6/12/2008 00:00:00
}
Sub DateTimeParseGermanExample()
    Dim MyCultureInfo As New CultureInfo("de-DE")
    Dim MyString As String = "12 Juni 2008"
    Dim MyDateTime As DateTime = DateTime.Parse(MyString, MyCultureInfo)
    Console.WriteLine(MyDateTime)
    ' The example displays the following output:
    '       6/12/2008 00:00:00
End Sub

Однако можно использовать перегрузки метода Parse для указания настраиваемых поставщиков форматов. Метод Parse не поддерживает синтаксический анализ форматов, отличных от стандартных. Чтобы проанализировать дату и время, выраженную в нестандартном формате, используйте вместо этого метод ParseExact.

Следующий пример использует перечисление DateTimeStyles, чтобы указать, что текущие сведения о дате и времени не должны быть добавлены в DateTime для неопределенных полей.

static void DateTimeParseNoDefaultExample()
{
    var cultureInfo = new CultureInfo("de-DE");
    string dateString = "12 Juni 2008";
    var dateTime = DateTime.Parse(dateString, cultureInfo,
                                    DateTimeStyles.NoCurrentDateDefault);
    Console.WriteLine(dateTime);
    // The example displays the following output if the current culture is en-US:
    //      6/12/2008 00:00:00
}
Sub DateTimeParseNoDefaultExample()
    Dim MyCultureInfo As New CultureInfo("de-DE")
    Dim MyString As String = "12 Juni 2008"
    Dim MyDateTime As DateTime = DateTime.Parse(MyString, MyCultureInfo,
                               DateTimeStyles.NoCurrentDateDefault)
    Console.WriteLine(MyDateTime)
    ' The example displays the following output if the current culture is en-US:
    '       6/12/2008 00:00:00
End Sub

DateTime.ParseExact

Метод DateTime.ParseExact преобразует строку в объект DateTime, если он соответствует одному из указанных шаблонов строк. Если строка, которая не является одной из указанных форм, передается этому методу, возникает FormatException. Можно указать один из стандартных описателей формата даты и времени или комбинацию настраиваемых описателей формата. С помощью пользовательских описателей формата можно создать настраиваемую строку распознавания. Описание спецификаций см. в статьях о строках стандартного формата даты и времени и, а также о настраиваемых форматах даты и времени .

В следующем примере метод DateTime.ParseExact передает строковый объект для синтаксического анализа, а затем описатель формата, за которым следует объект CultureInfo. Этот метод ParseExact может анализировать только строки, которые соответствуют шаблону длинной даты в культуре en-US.

static void DateTimeParseExactExample()
{
    // Parse exact format
    var exactDate = DateTime.ParseExact("2025-01-15T14:30:00", "yyyy-MM-ddTHH:mm:ss", CultureInfo.InvariantCulture);
    Console.WriteLine($"Exact parse: {exactDate}");

    // Parse with custom format
    var customDate = DateTime.ParseExact("15/Jan/2025 2:30 PM", "dd/MMM/yyyy h:mm tt", CultureInfo.InvariantCulture);
    Console.WriteLine($"Custom format: {customDate}");
}
Sub DateTimeParseExactExample()
    ' Parse exact format
    Dim exactDate = DateTime.ParseExact("2025-01-15T14:30:00", "yyyy-MM-ddTHH:mm:ss", CultureInfo.InvariantCulture)
    Console.WriteLine($"Exact parse: {exactDate}")

    ' Parse with custom format
    Dim customDate = DateTime.ParseExact("15/Jan/2025 2:30 PM", "dd/MMM/yyyy h:mm tt", CultureInfo.InvariantCulture)
    Console.WriteLine($"Custom format: {customDate}")
End Sub

Каждая перегрузка методов Parse и ParseExact также имеет параметр IFormatProvider, предоставляющий сведения о форматировании строки, которые зависят от языковых и культурных особенностей. Объект IFormatProvider — это объект CultureInfo, представляющий стандартные языковые параметры или объект DateTimeFormatInfo, возвращаемый свойством CultureInfo.DateTimeFormat. ParseExact также использует дополнительный аргумент строкового или строкового массива, определяющий один или несколько настраиваемых форматов даты и времени.

Синтаксический анализ DateOnly

Структура DateOnly представляет только дату без сведений о времени, что делает ее идеальной для таких сценариев, как дни рождения, анниверсы или даты бизнеса. Поскольку он не имеет компонента времени, он представляет дату с начала дня до конца дня.

DateOnly имеет несколько преимуществ по сравнению с использованием DateTime для работы только с датами:

  • Структура DateTime может сдвигаться в предыдущий или следующий день при смещении часового пояса. DateOnly не может корректироваться с учётом часового пояса и всегда отображает заданную дату.
  • При сериализации DateOnly включает меньше данных, чем DateTime.
  • При взаимодействии кода с базой данных, например SQL Server, все даты обычно хранятся как date тип данных, который не включает время. DateOnly лучше соответствует типу базы данных.

DateOnly.Parse

Метод DateOnly.Parse преобразует общие представления строк даты в DateOnly объект. Метод принимает различные форматы и использует текущую культуру или указанную культуру для синтаксического анализа.

static void DateOnlyParseExample()
{
    // Parse common date formats
    var date1 = DateOnly.Parse("1/15/2025");
    var date2 = DateOnly.Parse("January 15, 2025", CultureInfo.InvariantCulture);
    var date3 = DateOnly.Parse("2025-01-15");

    Console.WriteLine($"Parsed date: {date1}");
    Console.WriteLine($"Parsed date: {date2.ToString("D")}"); // Long date format
    Console.WriteLine($"Parsed date: {date3.ToString("yyyy-MM-dd")}");

    // Parse with specific culture
    var germanDate = DateOnly.Parse("15.01.2025", new CultureInfo("de-DE"));
    Console.WriteLine($"German date: {germanDate}");
}
Sub DateOnlyParseExample()
    ' Parse common date formats
    Dim date1 = DateOnly.Parse("1/15/2025")
    Dim date2 = DateOnly.Parse("January 15, 2025", CultureInfo.InvariantCulture)
    Dim date3 = DateOnly.Parse("2025-01-15")

    Console.WriteLine($"Parsed date: {date1}")
    Console.WriteLine($"Parsed date: {date2.ToString("D")}") ' Long date format
    Console.WriteLine($"Parsed date: {date3.ToString("yyyy-MM-dd")}")

    ' Parse with specific culture
    Dim germanDate = DateOnly.Parse("15.01.2025", New CultureInfo("de-DE"))
    Console.WriteLine($"German date: {germanDate}")
End Sub

DateOnly.ParseExact

Метод DateOnly.ParseExact предоставляет точный контроль над ожидаемым форматом входной строки. Используйте этот метод, если вы знаете точный формат строки даты и хотите обеспечить строгий анализ.

static void DateOnlyParseExactExample()
{
    // Parse exact format
    var exactDate = DateOnly.ParseExact("21 Oct 2015", "dd MMM yyyy", CultureInfo.InvariantCulture);
    Console.WriteLine($"Exact date: {exactDate}");

    // Parse ISO format
    var isoDate = DateOnly.ParseExact("2025-01-15", "yyyy-MM-dd", CultureInfo.InvariantCulture);
    Console.WriteLine($"ISO date: {isoDate}");

    // Parse with multiple possible formats
    string[] formats = { "MM/dd/yyyy", "M/d/yyyy", "dd/MM/yyyy" };
    var flexibleDate = DateOnly.ParseExact("1/15/2025", formats, CultureInfo.InvariantCulture, DateTimeStyles.None);
    Console.WriteLine($"Flexible parse: {flexibleDate}");
}
Sub DateOnlyParseExactExample()
    ' Parse exact format
    Dim exactDate = DateOnly.ParseExact("21 Oct 2015", "dd MMM yyyy", CultureInfo.InvariantCulture)
    Console.WriteLine($"Exact date: {exactDate}")

    ' Parse ISO format
    Dim isoDate = DateOnly.ParseExact("2025-01-15", "yyyy-MM-dd", CultureInfo.InvariantCulture)
    Console.WriteLine($"ISO date: {isoDate}")

    ' Parse with multiple possible formats
    Dim formats() As String = {"MM/dd/yyyy", "M/d/yyyy", "dd/MM/yyyy"}
    Dim flexibleDate = DateOnly.ParseExact("1/15/2025", formats, CultureInfo.InvariantCulture, DateTimeStyles.None)
    Console.WriteLine($"Flexible parse: {flexibleDate}")
End Sub

Метод ParseExact принимает одну строку формата или массив строк форматирования, что позволяет анализировать даты, которые могут поступать в нескольких допустимых форматах.

Синтаксический анализ TimeOnly

Структура TimeOnly представляет значение времени дня, например ежедневное будильник или время, когда вы едите обед каждый день. TimeOnly ограничен диапазоном 00:00:00.0000000 - 23:59:59.9999999, определенное время суток.

TimeOnly решает несколько проблем, которые существуют при использовании других типов для сценариев, связанных только со временем.

  • TimeSpan представляет истекшее время и может быть отрицательным или превышать 24 часа, что делает его непригодным для представления определенного времени дня.
  • Использование DateTime в течение дня требует произвольной даты, что может привести к неожиданному поведению при выполнении вычислений.
  • TimeOnly естественно обрабатывает 24-часовую откатку при добавлении или вычитания значений времени.

TimeOnly.Parse

Метод TimeOnly.Parse преобразует общие представления строк времени в TimeOnly объект. Метод принимает различные форматы, включая 12-часовую и 24-часовую нотацию.

static void TimeOnlyParseExample()
{
    // Parse common time formats
    var time1 = TimeOnly.Parse("14:30:15");
    var time2 = TimeOnly.Parse("2:30 PM", CultureInfo.InvariantCulture);
    var time3 = TimeOnly.Parse("17:45");

    Console.WriteLine($"Parsed time: {time1}");
    Console.WriteLine($"Parsed time: {time2.ToString("t")}"); // Short time format
    Console.WriteLine($"Parsed time: {time3.ToString("HH:mm")}");

    // Parse with milliseconds
    var preciseTime = TimeOnly.Parse("14:30:15.123");
    Console.WriteLine($"Precise time: {preciseTime.ToString("HH:mm:ss.fff")}");
}
Sub TimeOnlyParseExample()
    ' Parse common time formats
    Dim time1 = TimeOnly.Parse("14:30:15")
    Dim time2 = TimeOnly.Parse("2:30 PM", CultureInfo.InvariantCulture)
    Dim time3 = TimeOnly.Parse("17:45")

    Console.WriteLine($"Parsed time: {time1}")
    Console.WriteLine($"Parsed time: {time2.ToString("t")}") ' Short time format
    Console.WriteLine($"Parsed time: {time3.ToString("HH:mm")}")

    ' Parse with milliseconds
    Dim preciseTime = TimeOnly.Parse("14:30:15.123")
    Console.WriteLine($"Precise time: {preciseTime.ToString("HH:mm:ss.fff")}")
End Sub

TimeOnly.ParseExact

Метод TimeOnly.ParseExact предоставляет точный контроль над ожидаемым форматом входной строки времени. Используйте этот метод, если вы знаете точный формат и хотите обеспечить строгий анализ.

static void TimeOnlyParseExactExample()
{
    // Parse exact format
    var exactTime = TimeOnly.ParseExact("5:00 pm", "h:mm tt", CultureInfo.InvariantCulture);
    Console.WriteLine($"Exact time: {exactTime}");

    // Parse 24-hour format
    var militaryTime = TimeOnly.ParseExact("17:30:25", "HH:mm:ss", CultureInfo.InvariantCulture);
    Console.WriteLine($"Military time: {militaryTime}");

    // Parse with multiple possible formats
    string[] timeFormats = { "h:mm tt", "HH:mm", "H:mm" };
    var flexibleTime = TimeOnly.ParseExact("2:30 PM", timeFormats, CultureInfo.InvariantCulture, DateTimeStyles.None);
    Console.WriteLine($"Flexible time parse: {flexibleTime}");
}
Sub TimeOnlyParseExactExample()
    ' Parse exact format
    Dim exactTime = TimeOnly.ParseExact("5:00 pm", "h:mm tt", CultureInfo.InvariantCulture)
    Console.WriteLine($"Exact time: {exactTime}")

    ' Parse 24-hour format
    Dim militaryTime = TimeOnly.ParseExact("17:30:25", "HH:mm:ss", CultureInfo.InvariantCulture)
    Console.WriteLine($"Military time: {militaryTime}")

    ' Parse with multiple possible formats
    Dim timeFormats() As String = {"h:mm tt", "HH:mm", "H:mm"}
    Dim flexibleTime = TimeOnly.ParseExact("2:30 PM", timeFormats, CultureInfo.InvariantCulture, DateTimeStyles.None)
    Console.WriteLine($"Flexible time parse: {flexibleTime}")
End Sub

См. также