Я пытаюсь создать метод, который проверяет, правильно ли вставлены день, месяц и год. Метод возвращает 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!");
}
}
}
Отлично работает с CheckDate(1,1,2019)?
Это всего лишь простой пример. Я собираюсь добавить другие проверки позже. Сейчас я только проверяю, находится ли день от 1 до 31, месяц от 1 до 12, год от 1900 до 2100. @BrootsWaymb
DateTime уже умеет это делать, поэтому нет необходимости переопределять его. Вы можете использовать, например. static bool CheckDate(int d, int m, int y) { return min_year <= y && y <= max_year && DateTime.TryParse($"{y}-{m}-{d}", out _); }
.
как я это вижу, ничего плохого. за исключением того, что, как сказал Брутс, это вернет ложноположительный результат для недопустимой комбинации дат, то есть: 30 февраля 2010 г.
Не работает @RistoM
Если вы сделаете CheckDate(5, 2000, 123456)
, он вернет true
, потому что, как только ваш d находится между 1 и 31, вы всегда возвращаете true. То же самое для CheckDate(0, 5, 2000)
@RokŠekoranja возвращает true с CheckDate(1,1,2019)
: dotnetfiddle.net/Fv8qiR
Или вы можете сделать это:
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)
, который выдаст любую недопустимую дату.
Нет, это было бы неправильно, потому что вы будете управлять кодом, используя исключения. TryParse позволит избежать дорогостоящего исключения. Это будет намного быстрее с неверными датами.
Однако @derpirscher TryParseExact избегает создания исключения, и вы не хотите создавать исключения намеренно.
С точки зрения производительности создание исключений обходится дорого. Хорошая практика, чтобы избежать этого в «нормальной» логике проверки. Обновлено: 3 похожих комментария одновременно :)
Вместо того, чтобы возвращать результат TryParseExact, перехватите результат в такой переменной: var result = DateTime.TryParseExact. . . . И если это неверно, верните его, но если это правда, проверьте, что дата находится между 1 января 1900 года и 31 декабря 2100 года.
Где-то у меня в голове было, что методы .TryParse()
выполняют внутреннюю обработку исключений. Но видимо ошибся...
Я хочу указать на возможную ошибку и/или плохой дизайн в вашем установщике свойств (это может быть причиной вашего «Код всегда возвращает 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!");
}
}
}
Помимо вашей реальной проблемы, что, если я скажу ему подтвердить 31 апреля? Есть лучшие способы сделать это, когда вам не нужно создавать собственное решение.