Разбор дат без указания всех значений - PullRequest
14 голосов
/ 01 марта 2011

Я использую даты в свободной форме как часть синтаксиса поиска.Мне нужно разобрать даты из строк, но сохранить только те части даты, которые действительно указаны.Например, «1 ноября 2010 г.» - это конкретная дата, но «ноябрь 2010 г.» - это диапазон дат от «1 ноября 2010 г.» до «30 ноября 2010 г.».

К сожалению, DateTime.Parse идрузья разбирают эти даты на одно и то же DateTime:

DateTime.Parse("November 1, 2010") // == {11/1/2010 12:00:00 AM}
DateTime.Parse("November, 2010") // == {11/1/2010 12:00:00 AM}

Мне нужно знать, какие части DateTime были фактически проанализированы, а какие были угаданы анализатором.По сути, мне нужно DateTime.Parse("November, 2010") == {11/-1/2010 -1:-1:-1};Затем я вижу, что часть дня отсутствует, и вычисляю диапазон дат, охватывающий весь месяц.

(Внутренне C # имеет классы DateTimeParse и DateTimeResult, которые анализируют дату и сохраняют в точности информациюМне нужно, но к тому времени, когда дата возвращается к общедоступным интерфейсам, она удаляется. Я бы предпочел не отражать эти классы, если только это не единственный маршрут.)

Есть ли какой-то способ получитьDateTime.Parse чтобы сказать мне, в каком формате он анализировал дату?Или у возвращенного DateTime могут быть заполнители для неуказанных частей?Я также открыт для использования другого парсера дат, но я бы хотел, чтобы он был таким же надежным и гибким, как и внутренний.Заранее спасибо.

РЕДАКТИРОВАТЬ: Я также пытался ParseExact, но перечислить все форматы, которые Parse может обрабатывать кажется почти невозможно.Parse на самом деле принимает больше форматов, чем возвращается DateTimeFormatInfo.GetAllDateTimePatterns, что является почти таким же каноническим источником, как я могу найти.

Ответы [ 4 ]

2 голосов
/ 02 марта 2011

Parse анализирует множество вещей, которые ни один здравомыслящий человек не мог бы ввести в качестве даты, например "January / 2010 - 21 12: 00 :2". Я думаю, вам придется написать свой собственный анализатор дат, если вы хотите знать, что именно ввел пользователь.

Лично я бы сделал это так, как предложил KeithS: проанализируйте строку с Parse и вызовите свою собственную функцию синтаксического анализа, только если в одном из полей объекта DateTime есть 0. Нет таких возможностей, которые нужно проверять, потому что если день равен 0, время тоже будет равно 0. Итак, начните проверять год, месяц, день и т. Д.

Или просто проинструктируйте пользователя использовать определенные форматы, которые вы узнаете.

2 голосов
/ 01 марта 2011

Вы можете попробовать использовать TryParseExact (), который завершится ошибкой, если строка данных не соответствует указанному формату. Попробуйте несколько разных комбинаций, и когда вы добьетесь успеха, вы узнаете формат даты и, таким образом, вы знаете части даты, которых там не было и для которых парсер заполнил значения по умолчанию. Недостатком является то, что вы должны предвидеть, как пользователь захочет вводить даты, поэтому вы можете ожидать именно этого.

Вы также можете использовать регулярное выражение для переваривания строки даты самостоятельно. Опять же, вам понадобятся разные регулярные выражения (или ДЕЙСТВИТЕЛЬНО сложный одиночный), но, безусловно, можно также разбить строку на части; тогда вы знаете, что у вас есть на самом деле.

0 голосов
/ 15 сентября 2016

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

  • Для дней , исходная строка должна содержать1 как целое число, если был указан день.Итак, разбейте строку и найдите 1. Единственное исключение происходит, когда месяц - январь (# 1 месяц), поэтому вам следует проверить наличие двух 1 или 1 и «январь» или «январь» в исходной строке.
  • Для лет исходная строка должна содержать число, которое может быть годом (скажем, с 1900 до 2100).Другими возможностями может быть использование апострофа или таких вещей, как 02-10-16, которые вы можете узнать по факту, что существует ровно три числа.

Я знаю, что это довольно эвристично, но это быстрое и простое решение, которое работает в большинстве случаев.Я кодировал этот алгоритм в C # в DateFinder.DayExists() и DateFinder.YearExists() методах в библиотеке sharp-datefinder .

0 голосов
/ 01 марта 2011

По сути, мне нужно DateTime.Parse ("Ноябрь 2010") == {11 / -1 / 2010 -1: -1: -1}; Я могу тогда увидеть что часть дня отсутствует и рассчитать диапазон дат покрытия весь месяц.

То, что вы хотите, является недопустимым DateTime, потому что вы не можете иметь отрицательные значения часов / секунд / минут / дней. Если вы хотите вернуть что-то другое, кроме легального DateTime, вы должны написать свой собственный метод, который НЕ возвращает DateTime.

Есть ли способ получить DateTime.Parse, чтобы сказать мне, какой формат раньше разбирал дату? Или может возвращенный DateTime есть заполнители для неуказанных частей? Я тоже открыт использовать другой парсер дат, но я бы как быть надежным и гибкий, как внутренний.

Взгляните сюда http://msdn.microsoft.com/en-us/library/w2sa9yss.aspx

Вам нужно будет вручную отслеживать, что введено для выполнения этой задачи. Единственное решение - убедиться, что ввод введен в правильном формате.

...