检查给定的字符串是否为转换DateTime的有效格式字符串

时间:2019-06-28 13:52:43

标签: c# string validation string-formatting datetime-format

TLDR;

我需要验证给定的输入字符串是否为解析DateTime的有效“ 格式字符串”。例如,

  • yy-mm-dd有效
  • yy-aaaaaaa123无效

我正在研究program,它接受​​日期格式作为用户的输入。下面是我剥离的代码

private string datetimeFormat;

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

...
...
...

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

我需要为dateFormat字符串输入添加验证。

我正在考虑在数组中具有许多可能的组合,并且仅接受那些字符串。但是还有其他验证方法吗?


更新

我的输入字符串不包含任何日期。这不是specified question的副本。

This question与日期时间完全无关。

1 个答案:

答案 0 :(得分:2)

这种类型取决于您对“有效”的含义以及您认为“仅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,但可以通过它返回,但您可能希望返回一个简单的枚举值。)

这可以验证各种奇怪的格式,包括那些具有额外的非上下文(或至少非时间)字符的格式。样本包括一些针对时间值,订单反转等的测试。

但是有一些限制:

  • TryParseExact不能与d,'F'等standard format strings一起使用。
  • 它也不适用3位数以上的年份格式(yyy)和其他扩展格式。
  • 样本中包含一项防止使用两位数年份的测试。

简而言之,它足以完成简单的工作。您可以将其修剪一下。