Даты записываются в журналы следующим образом:

08 груд. 2017 00: 00: 06,694

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

var dateString = "08 груд. 2017 00:00:06,694";
DateTime date;

DateTime.TryParseExact(
    dateString, 
    "dd MMMM. yyyy HH:mm:ss,fff",
    new CultureInfo("uk-UA"), 
    DateTimeStyles.None, 
    out date);

Console.WriteLine(date);

Это не работает, и вывод этого сценария:

01.01.10001 00:00:00

Этот же подход хорошо сработал для меня для нескольких других языков, поэтому я озадачен тем, что здесь происходит. Насколько я могу судить, месяц анализируется неправильно. Попробую заменить "хруд". для значения месяца (из: https://www.loc.gov /aba/pcc/conser/conserhold/Mosabbr.html), но это тоже не работает.

c#
3
Jace 2 Янв 2018 в 19:39

2 ответа

Лучший ответ

Описатель формата месяца MMMM означает "полное название месяца". Вы можете увидеть полные названия месяцев для данной культуры с помощью:

var culture = new CultureInfo("uk-UA");
var monthNames = culture.DateTimeFormat.MonthNames;

Полное название декабря для этой культуры - «грудень», а не «груд». Вы можете подумать об использовании описателя формата "короткого названия месяца" MMM. Вы можете посмотреть "краткие названия" месяца для данной культуры следующим образом:

var culture = new CultureInfo("uk-UA");
var monthNames = culture.DateTimeFormat.AbbreviatedMonthNames;

Однако вы увидите, что декабрь сокращенно называется «гру», а не «груд». Итак, чтобы проанализировать вашу строку с названиями месяцев по умолчанию для вашей культуры, вам нужно либо сделать:

var dateString = "08 грудень 2017 00:00:06,694";
DateTime date;            
DateTime.TryParseExact(dateString, @"dd MMMM yyyy HH:mm:ss,fff", new CultureInfo("uk-UA"), DateTimeStyles.None, out date);

Или же

var dateString = "08 гру. 2017 00:00:06,694";
DateTime date;            
DateTime.TryParseExact(dateString, @"dd MMM. yyyy HH:mm:ss,fff", new CultureInfo("uk-UA"), DateTimeStyles.None, out date);

Другой вариант - отрегулировать названия месяцев культуры для вашего случая, как это (обратите внимание, что это не изменит глобальные настройки культуры, только название месяца для этого конкретного экземпляра CultureInfo, поэтому опасности нет при этом):

var dateString = "08 груд. 2017 00:00:06,694";
DateTime date;
var culture = new CultureInfo("uk-UA");
var defaultShortNames = culture.DateTimeFormat.AbbreviatedMonthNames;
var defaultShortGenitiveNames = culture.DateTimeFormat.AbbreviatedMonthGenitiveNames;
// obviously modify all month names as necessary
defaultShortNames[11] = "Груд";
defaultShortGenitiveNames[11] = "груд";
culture.DateTimeFormat.AbbreviatedMonthNames = defaultShortNames;
culture.DateTimeFormat.AbbreviatedMonthGenitiveNames = defaultShortGenitiveNames; 
// store this modified culture and reuse when necessary
// that MMM format consists of 3 letters is irrelevant - it will still
// work fine with abbreviated month names of 4 characters or more
DateTime.TryParseExact(dateString, @"dd MMM. yyyy HH:mm:ss,fff", culture, DateTimeStyles.None, out date);
4
Evk 2 Янв 2018 в 17:08

Как уже упоминалось, MMMM - это полное название месяца, а MMM - это сокращенное трехсимвольное название месяца, так что ни то, ни другое не будет работать из коробки. Вместо того, чтобы жестко кодировать названия месяцев или изменять CultureInfo, я бы предпочел предварительно обработать строку, чтобы усечь месяц до трех символов, которые можно анализировать с помощью строки настраиваемого формата MMM либо с помощью регулярных выражений (тяжеловес) или напрямую:

var sb = new StringBuilder (date.Length) ;
var nc = 0 ;
foreach (var ch in date)
{
    if (char.IsLetter (ch) && nc++ >= 3) continue ;
    sb.Append (ch) ;
}
return DateTime.ParseExact ("dd MMM. yyyy HH:mm:ss,fff", ...) ;
2
Anton Tykhyy 2 Янв 2018 в 17:11