Есть ли более быстрый способ проверить, действительно ли это действительная дата?

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

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

Ответ 1

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, этот код не будет работать быстрее, чем у вас сейчас. Тем не менее, я считаю, что вы получаете читаемость.

Ответ 2

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

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, поэтому он добавит накладные расходы ко всем хорошим датам.

Ответ 3

Хм... подумайте об этом так: класс 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...

Ответ 4

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

Ответ 5

РЕДАКТИРОВАТЬ: 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;
}

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

Ответ 6

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

DateTime.TryParse()

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

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

Ответ 7

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

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

Ответ 8

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