Как проверить, если путь (строка) содержит дату в формате переменного времени в C # .NET? - PullRequest
4 голосов
/ 26 июля 2011

Постановка задачи:

  • Существует путь, который содержит дату в определенном формате, который является параметром конфигурации. Скажите, "гггг_МММ_д",
  • Мне нужно определить, содержит ли путь такую ​​дату:
    • если это так, замените его на новую дату.
    • если нет, добавьте новую дату к пути
  • Существующей датой в пути может быть любая дата, не всегда вчерашняя или завтрашняя.

Попытка решения:

  • Обнаружение с помощью Regex (в примере \d{4}_[a-zA-Z]{3}_\d{1,2}) части, которая напоминает дату, и проверка ее впоследствии с использованием TryParseExact()
    • Это работает для постоянного формата, но мне нужно написать формат для поддержки компилятором regexp при изменении параметра. Это действительно не стоит усилий.

Итак, есть ли другое решение? Я думаю, что если нет лучшего способа, чем у меня, я мог бы потребовать параметр регулярного выражения рядом с параметром формата даты: -)

Ответы [ 2 ]

1 голос
/ 26 июля 2011

Почему бы не сохранить в конфигурации регулярное выражение и соответствующую строку формата для DateTime.ParseExact?

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

У вас все еще будет проблема с анализом даты, если вы не укажете ей формат или он соответствует стандартному формату.

Редактировать:Я надеюсь, что вы не возражаете против того, чтобы я как-то угадал вопрос, но мне было любопытно обсудить Regex, TryParseExact и Exception, поэтому я провел небольшой тест.Приведенный ниже код анализирует одно и то же имя файла 100 000 раз, чтобы определить и преобразовать внедренную дату.

Я удостоверился, что код запускается в режиме выпуска и без подключенного отладчика;обработка исключений при отладке в Visual Studio является убийцей.

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

Использование «неправильного» способа полагаться на обработку исключений былоно все же несколько иначе!

Мое время для кода, показанного ниже, было:

Using Regex:
Duration: 543.0543
Using TryParse:
Duration: 429.0429
Using Exceptions:
Duration: 11930.4865

Это время в миллисекундах.Первоначально я выполнял 1 миллион итераций, но мне было скучно, когда я выполнял «Исключения»; -)

Эксперимент показывает, что методы Regex и TryParseExact довольно сопоставимы по производительности, но метод TryParseExact имеет существенное значениеПреимущество в том, что ему не нужно определять или получать регулярное выражение.Без сомнения, это хороший выбор для этой проблемы.

Это также иллюстрирует накладные расходы на обработку исключения.Это не удивительно, так как процесс разматывания стека потенциально сложен и требует много времени.Приложение потратило 95% своего времени на обработку исключений.Это хорошо иллюстрирует аргумент, что вы не должны полагаться на обработку исключений для разбора даты - отсюда и существование методов TryParse ....

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Globalization;

namespace ConsoleApplication1
{
    class Program
    {
        static Regex r = new Regex(@"\d{4}_[a-zA-Z]{3}_\d{1,2}");
        static string dateFormat = "yyyy_MMM_d";
        static CultureInfo provider = CultureInfo.InvariantCulture;

        static void Main(string[] args)
        {
            string filepath = @"C:\TopDir\SubDir\2011_JUL_26\filename.ext";

            DateTime startTime;
            DateTime endTime;
            TimeSpan duration;
            bool success;
            DateTime result;

            System.Console.WriteLine("Using Regex:");
            startTime = DateTime.Now;
            for (int ix = 0; ix < 100000; ix++)
            {
                success = UsingRegex(filepath, out result);
            }
            endTime = DateTime.Now;
            duration = endTime - startTime;
            System.Console.WriteLine("Duration: " + duration.TotalMilliseconds.ToString());

            System.Console.WriteLine("Using TryParse:");
            startTime = DateTime.Now;
            for (int ix = 0; ix < 100000; ix++)
            {
                success = UsingTryParse(filepath, out result);
            }
            endTime = DateTime.Now;
            duration = endTime - startTime;
            System.Console.WriteLine("Duration: " + duration.TotalMilliseconds.ToString());

            System.Console.WriteLine("Using Exceptions:");
            startTime = DateTime.Now;
            for (int ix = 0; ix < 100000; ix++)
            {
                success = UsingExceptions(filepath, out result);
            }
            endTime = DateTime.Now;
            duration = endTime - startTime;
            System.Console.WriteLine("Duration: " + duration.TotalMilliseconds.ToString());
        }

        static bool UsingRegex(string filepath, out DateTime result)
        {
            var matches = r.Matches(filepath);

            if (matches.Count > 0)
            {
                return DateTime.TryParseExact(matches[0].Value, dateFormat, 
                          provider, DateTimeStyles.None, out result);
            }

            result = DateTime.MinValue;
            return false;
        }

        static bool UsingTryParse(string filepath, out DateTime result)
        {
            var parts = filepath.Split('\\');

            foreach (var part in parts)
            {
                if( DateTime.TryParseExact(part, dateFormat, provider, 
                      DateTimeStyles.None, out result) )
                {
                    return true;
                }
            }

            result = DateTime.MinValue;
            return false;
        }

        static bool UsingExceptions(string filepath, out DateTime result)
        {
            var parts = filepath.Split('\\');

            foreach (var part in parts)
            {
                try
                {
                    result = DateTime.ParseExact(part, dateFormat, 
                                provider, DateTimeStyles.None);
                    return true;
                }
                catch(Exception ex)
                {
                }
            }

            result = DateTime.MinValue;
            return false;
        }
    }
}
1 голос
/ 26 июля 2011

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

Заметьте, я не являюсь разработчиком .net, и поэтому это может быть что-то ужасное и неприятное, которое никогда не увидит свет ...

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