String仅包含给定的一组字符

时间:2010-07-20 18:51:11

标签: c# regex

我需要知道给定的字符串是否是有效的DateTime格式字符串,因为字符串可能代表其他内容。我尝试了DateTime.ParseExact(somedate.ToString(format),format),认为它会在无效格式上进行barf,但事实并非如此。

所以我很擅长测试字符串是否只包含“yYmMdDsShH”字符。像std :: string.find_first_not_of这样的东西可行,但System.String没有这个。

我认为RegEx可能会做到这一点,但我对正则表达式非常弱。

请注意,Linq不适用于此版本(仅限.NET 2.0)。

更新

为了澄清,我需要知道给定的字符串是否代表日期时间格式,而不是像这样的其他内容:

if (input == "some special value")
... // it's a special case value
else if (Environment.GetEnvironmentVariable(input))
... // it's an environment variable name
else if (IsDateTimeFormatString(input))
... // it's a date time format string
else if (input.IndexOfAny(Path.GetInvalidPathChars()) < 0)
... // it's a file path
else
   throw new Exception(); // Not a valid input

我可以将DateTime格式字符串限制为仅仅“yYmMdDsShH”,或者我也可以在其中添加一些分隔符,这取决于我允许或不允许的内容。

7 个答案:

答案 0 :(得分:36)

使用.NET2,您需要为此进行自己的检查。例如,以下方法使用foreach进行检查:

bool FormatValid(string format)
{
    string allowableLetters = "yYmMdDsShH";

    foreach(char c in format)
    {
         // This is using String.Contains for .NET 2 compat.,
         //   hence the requirement for ToString()
         if (!allowableLetters.Contains(c.ToString()))
              return false;
    }

    return true;
}

如果您可以选择使用.NET 3.5和LINQ,则可以使用Enumerable.Contains直接处理字符和Enumerable.All。这将简化以上内容:

bool valid = format.All(c => "yYmMdDsShH".Contains(c));

答案 1 :(得分:16)

像这样:

static readonly Regex Validator = new Regex(@"^[yYmMdDsShH]+$");

public static bool IsValid(string str) {
    return Validator.IsMatch(str);
}

正则表达式的工作原理如下:

  • ^匹配字符串的开头
  • [...]匹配括号中显示的任何字符
  • +匹配与上一项匹配的一个或多个字符
  • $匹配字符串的结尾

如果没有^$锚点,正则表达式将匹配包含至少一个有效字符的任何字符串,因为正则表达式可以匹配字符串的任何子字符串使用传递它。 ^$锚点强制它匹配整个字符串。

答案 2 :(得分:4)

我只是这样做:

public static class DateTimeFormatHelper
{
    // using a Dictionary<char, byte> instead of a HashSet<char>
    // since you said you're using .NET 2.0
    private static Dictionary<char, byte> _legalChars;

    static DateTimeFormatHelper()
    {
        _legalChars = new Dictionary<char, byte>();
        foreach (char legalChar in "yYmMdDsShH")
        {
            _legalChars.Add(legalChar, 0);
        }
    }

    public static bool IsPossibleDateTimeFormat(string format)
    {
        if (string.IsNullOrEmpty(format))
            return false; // or whatever makes sense to you

        foreach (char c in format)
        {
            if (!_legalChars.ContainsKey(c))
                return false;
        }

        return true;
    }
}

当然,这可能是一个过于严格的定义,因为它排除了大多数人会认为有效格式的内容,例如“yyyy-MM-dd”(因为它包含“ - ”字符)。

确切地确定您希望允许的字符是您的判断。

答案 3 :(得分:3)

这样的东西
Regex regex = new Regex("^(y|Y|m|M|d|D|s|S|h|H)+$");
if (regex.IsMatch('DateTime String'))
{
    // 'valid' 
}

如果你真的在搜索这些字符而不是给定日期和时间的数字表示

答案 4 :(得分:1)

Dan Tao的版本略有缩短,因为字符串表示IEnumerable&amp; lt&amp; char&gt;

的实现
   [TestClass]
   public class UnitTest1 {
      private HashSet<char> _legalChars = new HashSet<char>("yYmMdDsShH".ToCharArray());

      public bool IsPossibleDateTimeFormat(string format) {
         if (string.IsNullOrEmpty(format))
            return false; // or whatever makes sense to you
         return !format.Except(_legalChars).Any();
      }

      [TestMethod]
      public void TestMethod1() {
         bool result = IsPossibleDateTimeFormat("yydD");
         result = IsPossibleDateTimeFormat("abc");
      }
   }

答案 5 :(得分:0)

谢谢大家。我'恭喜'你们所有人,并坚持使用不使用Dictionary / HashSet并且不将字符转换为字符串的暴力实现:

private const string DateTimeFormatCharacters = "yYmMdDhHsS";
private static bool IsDateTimeFormatString(string input)
{
    foreach (char c in input)
        if (DateTimeFormatCharacters.IndexOf(c) < 0)
            return false;
    return true;
}

答案 6 :(得分:0)

有一个新项目NLib,可以更快地完成这项任务:

if (input.IndexOfNotAny(new char[] { 'y', 'm', 'd', 's', 'h' }, StringComparison.OrdinalIgnoreCase) < 0)
{
    // Valid
}
相关问题