Reputation: 1703
So i have a string in input that represent a format for a duration. This format can be of various type like : "hh:mm:ss" or "sssss" or ""hhmmss" etc...
My goal is to understand if this string, inserted by the user is a valid format. What i did until now :
Regex rgx = new Regex("[^a-zA-Z0-9 ]");
input = rgx.Replace(input, string.Empty);
At this point i have a string that should be in this format "hhmmss" or "sssss" or "mmss". I need to check if the user inserted some typo by mistake, doing a Regex.Match using this list of valid blocks
List<string> entry = new List<string> {
"h", "hh", "hhh", "hhhh",
"m", "mm", "mmm", "mmmm", "mmmmm",
"s", "ss", "sss", "ssss", "sssss" };
how can i do that?
EDIT: I'll try to explain some points. First of all, in this phase of my tool, i just need to check if the input from the user is valid. With valid, i mean that, any format that the user will enter (with separator or not), it is composed by at least the block of second. I am supossing that the user won't do anything like input = hsssmhhmms
cause it won't have any sense. The only thing i'll concede is a typo (for instance it press "g" instead of "h"). Of course the problem it's still hard, since this blocks of data can be wrapped in a multidute of forms. That is why i did that first step, to work on a compact block.
Upvotes: 1
Views: 120
Reputation: 461
Can you be sure that it is ordered? (h->m->s) Then it's:
var match = Regex.Match(input, "^([h]{0,4})[:]?([m]{0,5})[:]?([s]{0,5})$");
if (match.Success)
{
string hours = match.Groups[1].Value;
string mins = match.Groups[2].Value;
string secs = match.Groups[3].Value;
}
If not:
var match = Regex.Match(tbName.Text, "^([h]{0,4}|[m]{0,5}|[s]{0,5})[:]?([h]{0,4}|[m]{0,5}|[s]{0,5})[:]?([h]{0,4}|[m]{0,5}|[s]{0,5})$");
if (match.Success)
{
string hours = match.Groups.Cast<Group>().Skip(1).Select(x => x.Value).FirstOrDefault(x => x.Contains('h'));
string mins = match.Groups.Cast<Group>().Skip(1).Select(x => x.Value).FirstOrDefault(x => x.Contains('m'));
string secs = match.Groups.Cast<Group>().Skip(1).Select(x => x.Value).FirstOrDefault(x => x.Contains('s'));
}
You can test these Expressions here:
PS:
if you replace :
with \W_
it will allow other non-word character (,;-_? etc.)
?
stands for zero or one. -> you can have only one of them in between.
*
allows zero or many non-word character. -> so you can have something like: "hhh_-_--,.,;;mm,ssss"
Upvotes: 1
Reputation: 186668
Why not just try formatting? If system can format out then userFormat
is a correct format:
private static bool IsValidFormat(string userFormat) {
// Gini pig
TimeSpan sample = new TimeSpan(1234567);
string escaped = string.Concat(userFormat
.Select(c => char.IsLetter(c) || c == '%'
? c.ToString()
: "\\" + c.ToString())); // delimiters like :,;+... should be escaped
try {
sample.ToString(escaped);
return true;
}
catch (FormatException) {
return false;
}
}
...
// is this allowed? - true
Console.WriteLine(IsValidFormat(@"hh;mm;;ss+++ffff*h"));
// is this allowed? - false
Console.WriteLine(IsValidFormat(@"zzzz"));
Upvotes: 2