2015-04-23 5 views
2

Скажем, у меня есть строка, которая связана с консолью ввода и должен содержать данные о дате в любом из следующих форматов:Синтаксические входная строка C#

"dd/mm/yyyy" 
"dd.mm.yyyy" 
"dd,mm,yyyy" 

Что является самым безопасным способом, чтобы разобрать эту строку в DateTime объект ? Должен ли я использовать подход Regex или просто перебирать метод String.Format() со всеми возможными верхними форматами ввода до тех пор, пока он не удастся разобрать?

+1

Вы знаете, что культуры соответствуют этим значениям? Если вы это сделаете, вы можете передать их любой функции синтаксического анализа –

+0

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

+0

Возможно, вы захотите добавить '-'. Я вижу из Википедии, что он используется как разделитель в Германии, Франция –

ответ

1

Недостаточно использовать DateTime.ParseExact или DateTime.TryParseExact. / - специальный символ форматирования, символ разделителя даты. В строке формата он будет заменен любым разделителем даты для текущей культуры приложения. Этого нельзя избежать, потому что это не специальный символ, как \. Это вызовет проблемы, если в вашей системе используется . (Россия и другие страны).

Чтобы указать другой разделитель даты, вам нужно создать объект CultureInfo с нужным разделителем. Следующая функция принимает список разделителей и пытается выполнить разбор даты, используя каждый разделитель, пока один из них преуспевает:

public static bool TryParseDate(string input, string[] separators, out DateTime date) 
{ 
    var ci = (CultureInfo) CultureInfo.InvariantCulture.Clone(); 

    foreach (var separator in separators) 
    { 
     ci.DateTimeFormat.DateSeparator = separator; 
     DateTime result; 
     if (DateTime.TryParseExact(input, "dd/MM/yyyy", ci, DateTimeStyles.None, 
            out date)) 
      return true; 
    } 
    date=new DateTime(); 
    return false; 
} 

Там нет необходимости определять несколько форматов, потому что dd/MM/yyyy матчей всех случаев.

Это позволяет писать код, как в следующем фрагменте:

var separators = new []{"/",".",",","-"}; 
DateTime result; 
var success1 = TryParseDate("12.05.2015", separators, out result); 
var success2 = TryParseDate("12/05/2015", separators, out result); 
var success3 = TryParseDate("12,05,2015", separators, out result); 
var success4 = TryParseDate("12-05-2015", separators, out result); 

я добавил -, потому что я вижу, что это общий сепаратор в Германии. Вы можете сделать функцию еще более общей, передав формат в качестве другого параметра.

TryParseExact принимает несколько параметров формата. Если бы это было не для / сепаратора, вы могли бы написать один вызов со всеми форматами:

var formats=new []{"dd.MM.yyyy","dd,MM,yyyy","dd-MM-yyyy"}; 
DateTime result; 
var success=DateTime.TryParseExact(input, formats, 
         CultureInfo.InvariantCulture, DateTimeStyles.None, 
         out date) 
3

DateTime.ParseExact есть перегрузка, что вы можете поставить несколько формата к нему

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

Pass CultureInfo.InvariantCulture в IFormatProvider должен правильно обрабатывать разделитель для .,/

var dateformats = new[] { "dd/mm/yyyy", "dd.mm.yyyy", "dd,mm,yyyy" }; 

DateTime.ParseExact("23/04/2015", dateformats, CultureInfo.InvariantCulture, DateTimeStyles.None); 
DateTime.ParseExact("23.04.2015", dateformats, CultureInfo.InvariantCulture, DateTimeStyles.None); 
DateTime.ParseExact("23,04,2015", dateformats, CultureInfo.InvariantCulture, DateTimeStyles.None); 
+2

'DateTime.TryParseExact' - лучший вариант в этом случае, поскольку он не бросает, если он терпит неудачу. Реальная проблема заключается в том, что существует только * один * формат, но разделитель даты изменяется. OP должен будет передать пользовательский файл CultureInfo для каждой попытки. –

+0

@PanagiotisKanavos. Вы правы, но OP упомянутый '.. должен содержать данные даты в любом из следующих форматов', тогда' TryParseExact() 'ничего не добавляет к этому случаю. – Eric

+0

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

2

Вы должны использовать DateTime.TryParseExact, поскольку есть несколько форматов она не будет генерировать какие-либо исключения

Преобразует указанный строковое представление даты и времени на его эквивалент DateTime. Формат строкового представления должен точно соответствовать указанному формату. Метод возвращает значение, которое указывает, удалось ли преобразование.

+0

нет, насколько я могу судить по этому вопросу. – astralmaster

+0

Да @astralmaster, так как он не вызывает никаких исключений, если он терпит неудачу. – Tushar

+0

Не совсем. '/' - это символ разделителя даты, замененный разделителем * actual * от культуры пользователя.Разбор 'dd/mm/yyyy' не будет выполнен, если этот разделитель равен'. 'Или', '. –

1

DateTime.ParseExact Метод

Преобразует заданное строковое представление даты и времени ее DateTime эквивалент.

Или

DateTime.TryParseExact Метод

Преобразует заданное строковое представление даты и времени в его DateTime эквивалент. Формат строкового представления должен точно соответствовать указанному формату. Метод возвращает значение, которое указывает, удалось ли преобразование.

Примечание:

Анализировать принимает региональные настройки (культура текущего потока) в счет. Поэтому вам необходимо указать корректный формат с инвариантной культурой, например. ru-US

-1

Я считаю, что просто перебираем строку.Формат, возможно, проще, чем использовать регулярное выражение. Но если у вас есть фактические пользователи, которые вводят туда, где вы получили DateTimes, регулярное выражение безопаснее, но оно все равно должно быть окружено попыткой сделать его аварийным.

Смежные вопросы