Reputation: 14517
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.
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.
I thought that RegEx might do the trick, but I'm very weak with regular expressions.
Note that Linq is not available for this one (.NET 2.0 only).
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.
Upvotes: 27
Views: 50693
Reputation: 609
There's a new project, NLib, which can do this much faster:
if (input.IndexOfNotAny(new char[] { 'y', 'm', 'd', 's', 'h' }, StringComparison.OrdinalIgnoreCase) < 0)
{
// Valid
}
Upvotes: 0
Reputation: 14517
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:
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;
}
Upvotes: 2
Reputation: 564451
With .NET2, you need to roll your own check for this. For example, the following method uses a foreach to check:
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:
bool valid = format.All(c => "yYmMdDsShH".Contains(c));
Upvotes: 47
Reputation: 3866
Slightly shorted Dan Tao's version since string represents an implementation of IEnumerable<&char>
[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");
}
}
Upvotes: 1
Reputation: 887509
Like this:
static readonly Regex Validator = new Regex(@"^[yYmMdDsShH]+$");
public static bool IsValid(string str) {
return Validator.IsMatch(str);
}
The regex works like this:
^
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 stringWithout 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.
Upvotes: 30
Reputation: 125498
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
Upvotes: 4
Reputation: 128337
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).
Determining exactly what characters you wish to allow is your judgment call.
Upvotes: 4