Самый свободный способ разобрать дату / время в C #? - PullRequest
0 голосов
/ 17 мая 2018

Я анализирую широкий спектр RSS-каналов - по-видимому, все они используют свой собственный способ отображения метки времени статьи.

Теперь мы даже нашли тот, который использует локальные слова, такие как Donderdag 17 juli 2018.

На данный момент у нас есть механизм отката, при котором мы просто возвращаемся к DateTime.UtcNow, когда мы не можем проанализировать дату.

Тем не менее я хотел бы сделать лучшую попытку.Каков наилучший способ действительно свободно анализировать DateTime в C #?Таким образом, он может обрабатывать то есть:

  • 13-11-2018 14.32
  • donderdag 13 ноября 2018 года, 14: 32
  • 13 ноября 2018
  • 14: 32 13.11.2018
  • 2018-11-13T16: 32: 00 + 2: 00

и т. Д.Я знаю, что это не будет надежно, но все же я хотел бы сделать лучшую попытку.

Есть какой-нибудь рекомендуемый способ?Или я должен сам катиться?

Ответы [ 4 ]

0 голосов
/ 17 мая 2018

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

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

Вот код:

public static bool TryParseAllCultures(string formattedDate, 
    out DateTime result)
{
    // First try in our local culture
    if (DateTime.TryParse(formattedDate, out result)) return true;

    foreach (var cultureInfo in CultureInfo.GetCultures(CultureTypes.AllCultures))
    {
        if (DateTime.TryParse(formattedDate, cultureInfo, DateTimeStyles.None, 
            out result))
        {
            return true;
        }
    }

    return false;
}

Пример использования

Примечание: Я изменил одну из ваших дат, потому что сама дата была недействительной! Второй датой раньше было «donderdag 13 ноябрь 2018», за исключением 13-го - dienstag (вторник), а не donderdag (четверг).

private static void Main()
{
    DateTime date;

    var dateFormats = new List<string>
    {
        "13-11-2018 14.32",
        "donderdag 15 november 2018, 14:32",
        "13 nov 2018",
        "14:32 13.11.2018",
        "2018-11-13T16:32:00+2:00"
    };

    DateTime result;

    foreach (var dateFormat in dateFormats)
    {
        if (TryParseAllCultures(dateFormat, out result))
        {
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine($"SUCCESS: {dateFormat.PadRight(36, '.')} {result}");
        }
        else
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine($"ERROR: Unable to parse format: {dateFormat}");
        }

        Console.ResetColor();
    }

    GetKeyFromUser("\nDone! Press any key to exit...");
}

выход

enter image description here

0 голосов
/ 17 мая 2018

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

DateTime result;
if( DateTime.TryParseExact(input, new [] {"dd-MM-yyyy HH.mm", "dddd dd MMMM yyyy, HH:mm", "more formats here"}, CultureInfo.CreateSpecificCulture("nl-NL"), DateTimeStyles.None, out result)) {
  Console.WriteLine("Succeeded " + result);
}

Единственная большая «ошибка» здесь - это форматы датыгде дата и месяц находятся в неоднозначных позициях.Я не вижу ничего в вашем примере, но если бы вы смешали культуры в одном потоке, это могло бы стать проблемой.Например, в США обычно форматированная дата начинается с месяца, а в Нидерландах - с месяца.Если это проблема, то нет способа обработать это динамически в вашем случае использования выше , если только вы не получите культуру из потока RSS, и в этом случае вы можете попытаться создать набор правил синтаксического анализа, специфичных для культуры.

0 голосов
/ 17 мая 2018

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

первого октября, первого ноября, первого декабря, тринадцатого января и т. Д.

Единственный способ свободного разбора можно сделать несколько надежным, если можно использовать другие подсказки, чтобы связать даты с тем, что их написал.Если у вас есть несколько дат, которые встречаются на верхнем уровне определенного фида, и вы обнаружите, что все шаблоны синтаксического анализа, которые работают для всех них, дают одинаковые результаты, то, вероятно, этот шаблон синтаксического анализа правильно анализирует даты.Однако большая часть такой работы, скорее всего, будет заключаться не в разборе дат, а скорее в (1) обеспечении того, чтобы даты, записанные в разных форматах, группировались отдельно, и (2) в предоставлении средств, с помощью которых оператор может помочьпрограмма в тех местах, где возникают проблемы.

Кстати, я не знаю, используют ли какие-либо программы анализа дат присоединенные рабочие дни в качестве проверки формата, но они часто могут помочь.Например, «2-1-2018» может быть либо 2 января, либо 1 февраля, но «четверг 2-1-2018» может быть только последним.Это может быть полезно при разборе числовых дат из источника, формат которого еще не полностью установлен, чтобы определить, какой будет день недели для каждого метода синтаксического анализа, и проверить, содержит ли входные данные что-то, похожее на будний день, совпадающее с одним, но не с другим.

0 голосов
/ 17 мая 2018

Это предложение не относится к дате и времени, но вы можете попробовать использовать комбинаторы синтаксического анализа , особенно если вы решите применить собственное решение. Есть несколько библиотек для .net, например Sprache .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...