Этот тип зависит от того, что вы подразумеваете под «действительным» и насколько важно, по вашему мнению, ограничение «только DateTime
, ничего больше» для вас.
Вот несколько правил, которые мы можем использовать для тестирования строк формата, с некоторыми явными ограничениями:
Должно подходить для передачи в DateTime.ToString(string format)
для преобразования значения DateTime
в строку.
Должен использоваться для анализа результата правила 1 в допустимое значение DateTime
.
Вывод правила 2 не должен содержать часть времени.
При желании выходные данные правила 2 должны совпадать с выходными данными в пределах определенного диапазона точности.
Они будут достаточно хороши для многих применений, если вы ожидаете, что на выходе будет полностью указанная дата. Год, месяц и день должны быть указаны. Вот некоторый код для проверки этих правил:
static System.Globalization.CultureInfo DateTimeProvider = System.Globalization.CultureInfo.InvariantCulture;
const System.Globalization.DateTimeStyles ParseExactStyle = System.Globalization.DateTimeStyles.None;
static DateTime[] DateSamples = new[]
{
DateTime.Now,
DateTime.Today,
DateTime.Today.AddDays(1 - DateTime.Today.Day),
DateTime.Parse("10-Jan-2000"),
DateTime.Parse("01-Oct-1990"),
DateTime.Parse("13-Feb-1901")
};
public static bool IsValidDateFormat(string format, out string result)
{
var maxDifference = TimeSpan.FromDays(1);
foreach (var sample in DateSamples)
{
// Rule 1: Must be suitable for '.ToString(...)'
string sampleString;
try
{
sampleString = sample.ToString(format);
}
catch (FormatException e)
{
result = $"Failed rule 1: {e.Message}";
return false;
}
// Rule 2: Must be able to parse the produced string
if (!DateTime.TryParseExact(sampleString, format, DateTimeProvider, ParseExactStyle, out var parsed))
{
result = $"Failed rule 2: does not parse it's own output. '{sampleString}'";
return false;
}
// Rule 3: No time values.
if (parsed != parsed.Date)
{
result = $"Failed rule 3: No time values. '{sampleString}' => #{parsed}#";
return false;
}
// Rule 4: Difference must be less than maxDifference
TimeSpan difference = sample < parsed ? parsed - sample : sample - parsed;
if (difference >= maxDifference)
{
result = $"Failed rule 4: difference '{difference}' too large.";
return false;
}
}
result = "OK";
return true;
}
(Это устанавливает для параметра result
out описание причины сбоя строки формата или OK, если она прошла, но вы можете предпочесть вернуть простое значение enum.)
Это проверяет все странные форматы, в том числе с дополнительными неконтекстными или, по крайней мере, не временными символами. Образцы включают в себя несколько тестов против значений времени, изменение порядка и т. Д.
Однако есть некоторые ограничения:
TryParseExact
не работает с строками стандартного формата , такими как d
, 'F' и т. Д.
- Также он не работает с 3+-значным форматом года (
yyy
) и другими форматами растяжения.
- Образцы включают тест, который запрещает использование двухзначных лет.
Короче, этого достаточно для простой работы. Вы можете немного обрезать его назад.