Why not store in config the regex and the corresponding format string for DateTime.ParseExact?
Sure, you'll have to put some effort into working out the correct values, but then it's just a matter of updating the config and it's done.
You'll still have a problem parsing the date time unless you either tell it the format or it happens to fit a standard format, anyway.
Edit: I hope you don't mind me kind of hijacking the question, but I was curious with regard the discussion of Regex vs. TryParseExact vs. Exception handling, so I did a little test. The code, below, parses the same filename 100,000 times to identify and convert an embedded date.
I made sure to run the code in release mode and without the debugger attached; exception handling when debugging with Visual Studio is a killer.
I found that the Regex vs. TryParseExact methods were very close. Unsurprisingly, as the number of levels in the path increased, the Regex method became a little more efficient, but still nothing in it. If the path doesn't include a date at all, the balance shifts a little further towards the Regex method, but not enough to make a significant difference.
Using the 'incorrect' way of relying on exception handling was rather different, though!
My timings for the code shown below were:
Using Regex:
Duration: 543.0543
Using TryParse:
Duration: 429.0429
Using Exceptions:
Duration: 11930.4865
Those times are in milliseconds. I was originally running 1 million iterations, but I got bored when doing the Exceptions run ;-)
The experiment illustrates that the Regex and TryParseExact methods are pretty comparable in terms of performance, but the TryParseExact method has the significant advantage that it does not need a regex defining or deriving. Without doubt, it's a good choice for this problem.
It also illustrates the overhead of processing an exception. That's no surprise, really, either as the process of unwinding the stack is potentially time complex and time consuming. The application spent 95% of its time handling the exceptions. It illustrates the argument well, that you shouldn't rely on handling exceptions to parse date - hence the existence of the TryParse... methods.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Globalization;
namespace ConsoleApplication1
{
class Program
{
static Regex r = new Regex(@"\d{4}_[a-zA-Z]{3}_\d{1,2}");
static string dateFormat = "yyyy_MMM_d";
static CultureInfo provider = CultureInfo.InvariantCulture;
static void Main(string[] args)
{
string filepath = @"C:\TopDir\SubDir\2011_JUL_26\filename.ext";
DateTime startTime;
DateTime endTime;
TimeSpan duration;
bool success;
DateTime result;
System.Console.WriteLine("Using Regex:");
startTime = DateTime.Now;
for (int ix = 0; ix < 100000; ix++)
{
success = UsingRegex(filepath, out result);
}
endTime = DateTime.Now;
duration = endTime - startTime;
System.Console.WriteLine("Duration: " + duration.TotalMilliseconds.ToString());
System.Console.WriteLine("Using TryParse:");
startTime = DateTime.Now;
for (int ix = 0; ix < 100000; ix++)
{
success = UsingTryParse(filepath, out result);
}
endTime = DateTime.Now;
duration = endTime - startTime;
System.Console.WriteLine("Duration: " + duration.TotalMilliseconds.ToString());
System.Console.WriteLine("Using Exceptions:");
startTime = DateTime.Now;
for (int ix = 0; ix < 100000; ix++)
{
success = UsingExceptions(filepath, out result);
}
endTime = DateTime.Now;
duration = endTime - startTime;
System.Console.WriteLine("Duration: " + duration.TotalMilliseconds.ToString());
}
static bool UsingRegex(string filepath, out DateTime result)
{
var matches = r.Matches(filepath);
if (matches.Count > 0)
{
return DateTime.TryParseExact(matches[0].Value, dateFormat,
provider, DateTimeStyles.None, out result);
}
result = DateTime.MinValue;
return false;
}
static bool UsingTryParse(string filepath, out DateTime result)
{
var parts = filepath.Split('\\');
foreach (var part in parts)
{
if( DateTime.TryParseExact(part, dateFormat, provider,
DateTimeStyles.None, out result) )
{
return true;
}
}
result = DateTime.MinValue;
return false;
}
static bool UsingExceptions(string filepath, out DateTime result)
{
var parts = filepath.Split('\\');
foreach (var part in parts)
{
try
{
result = DateTime.ParseExact(part, dateFormat,
provider, DateTimeStyles.None);
return true;
}
catch(Exception ex)
{
}
}
result = DateTime.MinValue;
return false;
}
}
}