class RelativeDateParser
{
public static DateTime Parse(string input)
{
DateTime dt = DateTime.Now;
// parse "x days x hours x minutes x seconds" or "x days x hours x minutes x seconds ago"
Regex r = new Regex("(day)|(hour)|(minues)|(second)");
if (r.Match(input).Success == true)
{
dt = ParseDHMS(input);
}
// parse "yesterday" or "today" or "tomorrow" or "eow" or "eod"
r = new Regex("(today)|(tomorrow)|(eow)|(eod)");
if (r.Match(input).Success == true)
{
dt = ParseGenericRelative(input);
}
Console.WriteLine("Now DateTime: " + DateTime.Now.ToString());
Console.WriteLine("New DateTime: " + dt.ToString());
return dt;
}
private static DateTime ParseGenericRelative(string input)
{
throw new NotImplementedException("Not implemented");
}
private static DateTime ParseDHMS(string input)
{
DateTime dt;
double days = 0;
double hours = 0;
double minutes = 0;
double seconds = 0;
// search for days
Regex r = new Regex(@"(\d+)\s*day");
Match m = r.Match(input);
if (m.Success == true)
{
string match = m.Groups[1].Value;
days += Double.Parse(match);
}
// search for hours
r = new Regex(@"(\d+)\s*hour");
m = r.Match(input);
if (m.Success == true)
{
string match = m.Groups[1].Value;
hours += Double.Parse(match);
}
// search for minutes
r = new Regex(@"(\d+)\s*minute");
m = r.Match(input);
if (m.Success == true)
{
string match = m.Groups[1].Value;
minutes += Double.Parse(match);
}
// search for seconds
r = new Regex(@"(\d+)\s*second");
m = r.Match(input);
if (m.Success == true)
{
string match = m.Groups[1].Value;
seconds += Double.Parse(match);
}
// In past?
r = new Regex(@"ago");
m = r.Match(input);
if (m.Success == true)
{
days = days * -1;
hours = hours * -1;
minutes = minutes * -1;
seconds = seconds * -1;
}
/////////////////////
// Add offsets to now
dt = DateTime.Now.AddDays(days).AddHours(hours).AddMinutes(minutes).AddSeconds(seconds);
return dt;
}
}
Refactorings
No refactoring yet !
Elij
September 11, 2008, September 11, 2008 06:16, permalink
Please note I haven't tested/tried to build this -- same logic but with a bit of reuse
using System;
using System.Text.RegularExpressions;
class RelativeDateParser
{
public static DateTime Parse(string input)
{
DateTime dt = DateTime.Now;
// parse "x days x hours x minutes x seconds" or "x days x hours x minutes x seconds ago"
Regex r = new Regex("(day)|(hour)|(minues)|(second)");
if (r.Match(input).Success == true)
{
dt = ParseDHMS(input, dt);
}
// parse "yesterday" or "today" or "tomorrow" or "eow" or "eod"
r = new Regex("(today)|(tomorrow)|(eow)|(eod)");
if (r.Match(input).Success == true)
{
dt = ParseGenericRelative(input);
}
Console.WriteLine("Now DateTime: " + DateTime.Now.ToString());
Console.WriteLine("New DateTime: " + dt.ToString());
return dt;
}
private static DateTime ParseGenericRelative(string input)
{
throw new NotImplementedException("Not implemented");
}
private static DateTime ParseDHMS(string input, DateTime seedDtm)
{
TimeSpan timeSpan = new TimeSpan(0);
// search for days
timeSpan += TimeSpan.FromDays(getMetricValue(input, "day"));
// search for hours
timeSpan += TimeSpan.FromHours(getMetricValue(input, "hour"));
// search for minutes
timeSpan += TimeSpan.FromMinutes(getMetricValue(input, "minutes"));
// search for seconds
timeSpan += TimeSpan.FromSeconds(getMetricValue(input, "second"));
return seedDtm.AddTicks(timeSpan.Ticks * (int)(input.EndsWith("ago") ? -1 : 1));
}
private static double getMetricValue(string input, string metric)
{
Regex r = new Regex(@"(\d+)\s*" + metric);
Match m = r.Match(input);
if (m.Success)
{
string match = m.Groups[1].Value;
return Double.Parse(match);
}
return 0;
}
}
I'd like to build up something to cover many relative date formats