Как проверить, действительна ли дата с 3 целыми числами? (Метод возврата bool)

Я пытаюсь создать метод, который проверяет, правильно ли вставлены день, месяц и год. Метод возвращает TRUE, если дата в порядке, и FALSE, если дата НЕ в порядке. Проблема: код всегда возвращает false.

const int max_year = 2100;
const int min_year = 1900;

static bool CheckDate(int d, int m, int y)   
{
    if (d < 1 || d > 31)
    {
        if (m < 1 || m > 12)
        {
            if (y < min_year || y > max_year)
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        else
        {
            return true;
        }
    }
    else
    {
        return true;
    }
}

И затем я проверяю дату в свойстве, например:

public int Day
{
    get
    {
        return day;
    }
    set
    {
        if (CheckDate(dan, mesec, year) == true)
        {
            day = value;
        }
        else
        {
            throw new Exception("Day is incorrect!");
        }
    }
}

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

Broots Waymb 10.04.2019 18:24

Отлично работает с CheckDate(1,1,2019)?

Risto M 10.04.2019 18:26

Это всего лишь простой пример. Я собираюсь добавить другие проверки позже. Сейчас я только проверяю, находится ли день от 1 до 31, месяц от 1 до 12, год от 1900 до 2100. @BrootsWaymb

Rok Šekoranja 10.04.2019 18:26

DateTime уже умеет это делать, поэтому нет необходимости переопределять его. Вы можете использовать, например. static bool CheckDate(int d, int m, int y) { return min_year <= y && y <= max_year && DateTime.TryParse($"{y}-{m}-{d}", out _); }.

ckuri 10.04.2019 18:26

как я это вижу, ничего плохого. за исключением того, что, как сказал Брутс, это вернет ложноположительный результат для недопустимой комбинации дат, то есть: 30 февраля 2010 г.

Nii 10.04.2019 18:27

Не работает @RistoM

Rok Šekoranja 10.04.2019 18:27

Если вы сделаете CheckDate(5, 2000, 123456), он вернет true, потому что, как только ваш d находится между 1 и 31, вы всегда возвращаете true. То же самое для CheckDate(0, 5, 2000)

derpirscher 10.04.2019 18:27

@RokŠekoranja возвращает true с CheckDate(1,1,2019): dotnetfiddle.net/Fv8qiR

Risto M 10.04.2019 18:28
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
8
178
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Или вы можете сделать это:

static bool CheckDate(int d, int m, int y) 
{
   try
   {
      // This will throw an exception if the year, month or day are invalid
      var temp = new DateTime(y, m, d);
      return true;
   }
   except
   {
     return false;
   }
}

Как можно проще, просто преобразуйте свои числа в строку, а затем выполните DateTime.TryParseExact в формате ггггММдд.

bool CheckDate(int y, int m, int d)
{

    string t = $"{y:D4}{m:D2}{d:D2}";
    return DateTime.TryParseExact(t, "yyyyMMdd", CultureInfo.InvariantCulture,DateTimeStyles.None,  out DateTime dt);
}

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

if (y < min_year || y > max_year)
    return false;
....

Вам не нужно создавать строку и снова анализировать ее. Вы можете просто попытаться создать new DateTime(y, m, d), который выдаст любую недопустимую дату.

derpirscher 10.04.2019 18:43

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

Steve 10.04.2019 18:47

Однако @derpirscher TryParseExact избегает создания исключения, и вы не хотите создавать исключения намеренно.

Joseph White 10.04.2019 18:47

С точки зрения производительности создание исключений обходится дорого. Хорошая практика, чтобы избежать этого в «нормальной» логике проверки. Обновлено: 3 похожих комментария одновременно :)

Risto M 10.04.2019 18:47

Вместо того, чтобы возвращать результат TryParseExact, перехватите результат в такой переменной: var result = DateTime.TryParseExact. . . . И если это неверно, верните его, но если это правда, проверьте, что дата находится между 1 января 1900 года и 31 декабря 2100 года.

Joseph White 10.04.2019 18:48

Где-то у меня в голове было, что методы .TryParse() выполняют внутреннюю обработку исключений. Но видимо ошибся...

derpirscher 10.04.2019 18:57
Ответ принят как подходящий

Я хочу указать на возможную ошибку и/или плохой дизайн в вашем установщике свойств (это может быть причиной вашего «Код всегда возвращает false»).

Если вы присмотритесь, то увидите, что CheckDate всегда вызывается с параметрами dan, mesec и year. Как вы знаете, value — это устанавливаемое значение (Day = 1 или Day = 500), но оно не является частью CheckDate-вызова.

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

public int Day
{
    get
    {
        return day;
    }
    set
    {
        // Why this?
        if (CheckDate(dan, mesec, year) == true)
        {
            day = value;
        }
        else
        {
            throw new Exception("Day is incorrect!");
        }
    }
}

Другие вопросы по теме