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

#c# #methods #properties #boolean

#c# #методы #свойства #логическое

Вопрос:

Я пытаюсь создать метод, который проверяет, правильно ли вставлены день, месяц и год. Метод возвращает 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!");
        }
    }
}
  

Комментарии:

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

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

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

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

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

Ответ №1:

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

 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);
}
  

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

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

Комментарии:

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

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

3. @derpirscher TryParseExact позволяет избежать создания исключения, хотя и вы не хотите специально создавать исключения.

4. С точки зрения производительности, создание исключения обходится дорого. Рекомендуется избегать этого в «обычной» логике проверки. РЕДАКТИРОВАТЬ: 3 похожих комментария одновременно 🙂

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

Ответ №2:

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

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

Если это ваша цель, я могу сказать, что это очень плохой дизайн. Вы должны вызывать 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!");
        }
    }
}
  

Ответ №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;
   }
}