Проверьте, является ли данная строка допустимой строкой формата для преобразования DateTime - PullRequest
1 голос
/ 28 июня 2019

TLDR;

Мне нужно проверить, является ли данная входная строка действительной « строкой формата » для анализа DateTime.Например,

  • yy-mm-dd допустимо
  • yy-aaaaaaa123 недопустимо

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

private string datetimeFormat;

public Logger(string dateFormat)
{
    datetimeFormat = dateFormat;
}

...
...
...

// Inside some function
string pretext = $"{DateTime.Now.ToString(datetimeFormat)},{logLevel},";

Мне нужно добавить проверку для строкового ввода dateFormat.

Я имею в виду наличие множества возможных комбинаций в массиве и принимаю только тестроки.Но есть ли другой способ проверки?


Обновления :

Моя входная строка не содержит никакой даты.Это не дубликат указанного вопроса .

Этот вопрос вообще не касается DateTime.

1 Ответ

2 голосов
/ 28 июня 2019

Этот тип зависит от того, что вы подразумеваете под «действительным» и насколько важно, по вашему мнению, ограничение «только DateTime, ничего больше» для вас.

Вот несколько правил, которые мы можем использовать для тестирования строк формата, с некоторыми явными ограничениями:

  1. Должно подходить для передачи в DateTime.ToString(string format) для преобразования значения DateTime в строку.

  2. Должен использоваться для анализа результата правила 1 в допустимое значение DateTime.

  3. Вывод правила 2 не должен содержать часть времени.

  4. При желании выходные данные правила 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) и другими форматами растяжения.
  • Образцы включают тест, который запрещает использование двухзначных лет.

Короче, этого достаточно для простой работы. Вы можете немного обрезать его назад.

...