字符串只包含给定的一组字符

时间:2022-09-13 11:45:36

I need to know if a given string is a valid DateTime format string because the string may represent other things. I tried DateTime.ParseExact(somedate.ToString(format), format) thinking it would barf on an invalid format, but it doesn't.

我需要知道一个给定的字符串是否是一个有效的DateTime格式字符串,因为这个字符串可能代表其他东西。我尝试了DateTime.ParseExact(somedate.ToString(format), format),认为它会以无效的格式出现问题,但事实并非如此。

So I'm good with simply testing if the string contains only "yYmMdDsShH" characters. Something like std::string.find_first_not_of would work, but System.String doesn't have this.

所以我很擅长简单地测试字符串是否只包含“yYmMdDsShH”字符。类似的std::string。find_first_not_of可以工作,但是系统。没有这个字符串。

I thought that RegEx might do the trick, but I'm very weak with regular expressions.

我认为RegEx可能会起到这个作用,但我在正则表达式方面非常弱。

Note that Linq is not available for this one (.NET 2.0 only).

注意,Linq不能用于这个(。NET 2.0)。

Updated

更新

To clarify, I need to know if a given string represents a date time format and not something else like this:

为了澄清这一点,我需要知道给定的字符串是否表示日期时间格式,而不是其他类似的格式:

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

I can restrict a DateTime format string to only "yYmMdDsShH", or I can add a few separator characters into it as well, it's up to me what to allow or not allow.

我可以将DateTime格式字符串限制为“yYmMdDsShH”,也可以在其中添加一些分隔符,由我决定允许与否。

7 个解决方案

#1


31  

With .NET2, you need to roll your own check for this. For example, the following method uses a foreach to check:

使用。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;
}

If you had the option of using .NET 3.5 and LINQ, you could use Enumerable.Contains to work with characters directly, and Enumerable.All. This would simplify the above to:

如果您有使用。net 3.5和LINQ的选项,您可以使用Enumerable。包含直接处理字符,并可枚举。all。这将把上面的内容简化为:

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

#2


15  

Like this:

是这样的:

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

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

The regex works like this:

regex的工作方式如下:

  • ^ matches the beginning of the string
  • ^匹配字符串的开始
  • [...] matches any of the characters that appear in the brackets
  • […匹配括号中出现的任何字符
  • + matches one or more characters that match the previous item
  • +匹配一个或多个与前一项匹配的字符
  • $ matches the end of the string
  • $匹配字符串的末尾

Without the ^ and $ anchors, the regex will match any string that contains at least one valid character, because a regex can match any substring of the string use pass it. The ^ and $ anchors force it to match the entire string.

没有^和$锚,regex将匹配任何字符串,该字符串包含至少一个有效字符,因为正则表达式可以匹配任何字符串的子串使用通过它。^和$锚力它匹配整个字符串。

#3


4  

I'd just do this:

我只是这样做:

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;
    }
}

Of course, this might be an excessively strict definition, as it rules out what most people would consider valid formats such as "yyyy-MM-dd" (since that includes "-" characters).

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

Determining exactly what characters you wish to allow is your judgment call.

决定你想要的角色是你的判断。

#4


2  

Something like

类似的

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

if you're literally searching for those characters and not the numerical representation for a given date and time

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

#5


1  

Slightly shorted Dan Tao's version since string represents an implementation of IEnumerable&lt&char>

由于字符串表示IEnumerable<&char>的实现,所以略微缩短了Dan Tao的版本

   [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");
      }
   }

#6


0  

Thank you everyone. I 'upped' all of you and settled on a brute force implementation that doesn't use a Dictionary/HashSet and doesn't convert chars to strings:

谢谢每一个人。我“升级”了你们所有人,并确定了一个蛮力实现,它不使用字典/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;
}

#7


0  

There's a new project, NLib, which can do this much faster:

有一个新项目,NLib,可以做得更快:

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

#1


31  

With .NET2, you need to roll your own check for this. For example, the following method uses a foreach to check:

使用。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;
}

If you had the option of using .NET 3.5 and LINQ, you could use Enumerable.Contains to work with characters directly, and Enumerable.All. This would simplify the above to:

如果您有使用。net 3.5和LINQ的选项,您可以使用Enumerable。包含直接处理字符,并可枚举。all。这将把上面的内容简化为:

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

#2


15  

Like this:

是这样的:

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

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

The regex works like this:

regex的工作方式如下:

  • ^ matches the beginning of the string
  • ^匹配字符串的开始
  • [...] matches any of the characters that appear in the brackets
  • […匹配括号中出现的任何字符
  • + matches one or more characters that match the previous item
  • +匹配一个或多个与前一项匹配的字符
  • $ matches the end of the string
  • $匹配字符串的末尾

Without the ^ and $ anchors, the regex will match any string that contains at least one valid character, because a regex can match any substring of the string use pass it. The ^ and $ anchors force it to match the entire string.

没有^和$锚,regex将匹配任何字符串,该字符串包含至少一个有效字符,因为正则表达式可以匹配任何字符串的子串使用通过它。^和$锚力它匹配整个字符串。

#3


4  

I'd just do this:

我只是这样做:

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;
    }
}

Of course, this might be an excessively strict definition, as it rules out what most people would consider valid formats such as "yyyy-MM-dd" (since that includes "-" characters).

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

Determining exactly what characters you wish to allow is your judgment call.

决定你想要的角色是你的判断。

#4


2  

Something like

类似的

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

if you're literally searching for those characters and not the numerical representation for a given date and time

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

#5


1  

Slightly shorted Dan Tao's version since string represents an implementation of IEnumerable&lt&char>

由于字符串表示IEnumerable<&char>的实现,所以略微缩短了Dan Tao的版本

   [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");
      }
   }

#6


0  

Thank you everyone. I 'upped' all of you and settled on a brute force implementation that doesn't use a Dictionary/HashSet and doesn't convert chars to strings:

谢谢每一个人。我“升级”了你们所有人,并确定了一个蛮力实现,它不使用字典/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;
}

#7


0  

There's a new project, NLib, which can do this much faster:

有一个新项目,NLib,可以做得更快:

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