解析字符串输入 C#

Parsing string input C#

假设我有一个绑定到控制台输入的字符串,并且必须包含以下任何格式的日期数据:

"dd/mm/yyyy"
"dd.mm.yyyy"
"dd,mm,yyyy"

将此字符串解析为 DateTime 对象的最安全方法是什么?我应该使用 Regex 方法还是简单地使用上面提到的所有可能的输入格式迭代 String.Format() 方法直到它成功解析?

DateTime.ParseExact 确实有一个重载,您可以为其提供多种格式

Converts the specified string representation of a date and time to its DateTime equivalent using the specified array of formats, culture-specific format information, and style. The format of the string representation must match at least one of the specified formats exactly or an exception is thrown.

CultureInfo.InvariantCulture 传递给 IFormatProvider 应该正确处理 . , /

的分隔符
var dateformats = new[] { "dd/mm/yyyy", "dd.mm.yyyy", "dd,mm,yyyy" };

DateTime.ParseExact("23/04/2015", dateformats, CultureInfo.InvariantCulture, DateTimeStyles.None);
DateTime.ParseExact("23.04.2015", dateformats, CultureInfo.InvariantCulture, DateTimeStyles.None);
DateTime.ParseExact("23,04,2015", dateformats, CultureInfo.InvariantCulture, DateTimeStyles.None);

您需要使用 DateTime.TryParseExact 因为有多种格式它不会产生任何异常

Converts the specified string representation of a date and time to its DateTime equivalent. The format of the string representation must match a specified format exactly. The method returns a value that indicates whether the conversion succeeded.

DateTime.ParseExact 方法

Converts the specified string representation of a date and time to its DateTime equivalent.

DateTime.TryParseExact 方法

Converts the specified string representation of a date and time to its DateTime equivalent. The format of the string representation must match a specified format exactly. The method returns a value that indicates whether the conversion succeeded.

注:

Parse takes regional settings (culture of current thread) into account. Therefore, you need to specify the correct format explicitly with an invariant culture eg. en-US

我认为只需遍历 String.Format,这可能比使用正则表达式更容易。但是,如果您有实际用户输入到您获得 DateTimes 的任何地方,则正则表达式更安全,但它仍然应该被尝试使其防崩溃。

使用DateTime.ParseExact或DateTime.TryParseExact是不够的。 / 是一个特殊的格式字符,日期分隔符。在格式字符串中,它将替换为应用程序当前区域性的任何日期分隔符。它无法转义,因为它 不是 \ 这样的特殊字符。如果您的系统文化使用 .(俄罗斯和其他国家/地区),这将导致问题。

要指定不同的日期分隔符,您需要使用所需的分隔符创建一个 CultureInfo 对象。以下函数接受分隔符列表并尝试使用每个分隔符解析日期,直到其中一个成功:

public static bool TryParseDate(string input, string[] separators, out DateTime date)
{
    var ci = (CultureInfo) CultureInfo.InvariantCulture.Clone();

    foreach (var separator in separators)
    {
        ci.DateTimeFormat.DateSeparator = separator;
        DateTime result;
        if (DateTime.TryParseExact(input, "dd/MM/yyyy", ci, DateTimeStyles.None, 
                                   out date))
            return true;
    }
    date=new DateTime();
    return false;
}

无需定义多种格式,因为 dd/MM/yyyy 匹配所有大小写。

这样您就可以编写如下代码片段:

var separators = new []{"/",".",",","-"};
DateTime result;
var success1 = TryParseDate("12.05.2015", separators, out result);
var success2 = TryParseDate("12/05/2015", separators, out result);
var success3 = TryParseDate("12,05,2015", separators, out result);
var success4 = TryParseDate("12-05-2015", separators, out result);

我添加了 -,因为我看到它在德国是一种常见的分隔符。您可以通过将格式作为另一个参数传递来使该函数更加通用。

TryParseExact 接受多个格式参数。如果不是 / 分隔符,您可以使用所有格式编写一个调用:

var formats=new []{"dd.MM.yyyy","dd,MM,yyyy","dd-MM-yyyy"};
DateTime result;
var success=DateTime.TryParseExact(input, formats, 
                       CultureInfo.InvariantCulture, DateTimeStyles.None, 
                       out date)