2011-03-01 1 views
14

Я использую даты свободной формы как часть синтаксиса поиска. Мне нужно анализировать даты из строк, но сохранять только те части даты, которые указаны на самом деле. Например, «ноябрь 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 есть заполнители для неуказанных частей? Я также открыт для использования другого синтаксического анализа даты, но я бы хотел, чтобы он был таким же надежным и локальным, как и внутренний. Заранее спасибо.

EDIT: Я также пробовал ParseExact, но перечисление всех форматов, которые может обрабатывать Parse, кажется почти невозможным. Parse на самом деле принимает больше форматов, чем возвращается DateTimeFormatInfo.GetAllDateTimePatterns, который примерно как канонический источник, как я могу найти.

ответ

2

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

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

+0

См. Мое редактирование выше. ParseExact оказывается недостаточным для общего синтаксического анализа даты. – kevingessner

0

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

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

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

Посмотрите здесь http://msdn.microsoft.com/en-us/library/w2sa9yss.aspx

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

+3

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

+1

Майкл Прайор прав, я имел в виду -1 как просто место для неуказанных частей. – kevingessner

2

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

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

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

+1

«Разбирайте строку с помощью Parse и вызывайте только свою собственную функцию синтаксического анализа, если в одном из полей объекта DateTime есть 0». - К сожалению, дневная часть DateTime никогда не может быть 0. Она установлена ​​в 1, если не указано, что невозможно отличить от нее, как указано как 1. – kevingessner

0

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

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

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