Есть ли более быстрый способ проверить, является ли это действительной датой? - PullRequest
11 голосов
/ 17 мая 2010

Есть ли более быстрый способ, чем просто поймать исключение, как показано ниже?

try
{
    date = new DateTime(model_.Date.Year, model_.Date.Month, (7 * multiplier) + (7 - dow) + 2);
}
catch (Exception)
{
    // This is an invalid date
}

Ответы [ 8 ]

15 голосов
/ 17 мая 2010
String DateString = String.Format("{0}/{1}/{2}", model_.Date.Month, (7 * multiplier) + (7 - dow) + 2),model_.Date.Year);

DateTime dateTime;
if(DateTime.TryParse(DateString, out dateTime))
{
    // valid
}

Как отмечается в комментарии GenericTypeTea, этот код не будет работать быстрее, чем у вас сейчас.Тем не менее, я верю, что вы улучшаете читабельность.

9 голосов
/ 17 мая 2010

Если ваша цель состоит в том, чтобы избежать использования исключений, вы можете написать собственный метод проверки:

public bool IsValidDate(int year, int month, int multiplier, int dow)
{
    if (year < 1 | year > 9999) { return false; }

    if (month < 1 | month > 12) { return false; }

    int day = 7 * multiplier + 7 - dow;
    if (day < 1 | day > DateTime.DaysInMonth(year, month)) { return false; }

    return true;
}

Он выполняет большинство тех же проверок, что и используемый вами конструктор DateTime, - он только пропускает проверку, чтобы увидеть, будет ли результирующий DateTime меньше DateTime.MinValue или больше DateTime.MaxValue.

Если вы в большинстве случаев получаете хорошие значения, это, вероятно, будет в целом медленнее: DateTime.DaysInMonth должен делать то же самое, что и конструктор DateTime, поэтому он добавляет накладные расходы ко всем хорошим датам.

5 голосов
/ 17 мая 2010

Хм ... подумайте об этом так: класс model_ имеет свойство DateTime

model_.Date

, поэтому не нужно проверять год и месяц. Единственная сложная часть - день месяца:

(7 * multiplier) + (7 - dow) + 2

Таким образом, очень быстрый и эффективный способ проверить это (что лучше, чем бросать и ловить) - это использовать метод DateTime.DaysInMonth:

if ((multiplier <= 4) && 
    (DateTime.DaysInMonth(model_.Date.Year, model_.Date.Month) < 
        (7 * multiplier) + (7 - dow) + 2))
{
    // error: invalid days for the month/year combo...
}

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

P.S. Обновлен код, чтобы гарантировать, что множитель равен <= 4. Это имеет смысл, поскольку любое значение> = 5 не пройдет тест DaysInMonth ...

2 голосов
/ 17 мая 2010

РЕДАКТИРОВАТЬ : Woops! DateTime.TryParse не вызывает внутреннее исключение. Я говорил своими ягодицами! Во всяком случае ...

DateTime.TryParse() вызовет внутреннее исключение и вызовет результат, идентичный вашему коду в вашем вопросе. Если скорость не важна, вам придется написать собственный метод.

Это может показаться большим количеством кода, но я думаю, что это будет быстрее, если вы ожидаете большой объем ошибок:

public bool GetDate(int year, int month, int day, out DateTime dateTime)
{
    if (month > 0 && month <= 12)
    {
        int daysInMonth = DateTime.DaysInMonth(year, month);
        if (day <= daysInMonth)
        {
            dateTime = new DateTime(year, month, day);
            return true;
        }
    }
    dateTime = new DateTime();
    return false;
}

Мой приведенный выше пример не будет обрабатывать все случаи (т. Е. Я не занимаюсь годами), но он укажет вам правильное направление.

2 голосов
/ 17 мая 2010

Посмотрите на DateTime.TryParse метод

1 голос
/ 17 мая 2010

Я не знаю, быстрее, но

DateTime.TryParse()

Должен делать то же самое.

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

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

Хотя одна вещь: исключения для исключительных случаев. Богоформатированные строки не являются исключительными, но ожидаемыми, поэтому TryParse является более подходящим.

Использование try / catch для проверки правильности - это неправильное использование и неправильное представление об исключениях, особенно с универсальным уловом (последний уже заставил меня искать часы, почему что-то не работает, и столько раз).

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

Если механизм синтаксического анализа работает не так быстро, вы можете использовать несколько более подробный метод проверки свойств объекта модели на предмет допустимых значений напрямую.

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