Here is a solution that uses a Binary Search.
You need to have a list of DateTime
s, no question about it. No point in keeping them as string
s, parse them on the way into the list if you have to. You can use LINQ to convert all the elements in the list, but that's the only way you'll be able to compare dates with eachother.
Check out the page for BinarySearch
to understand why I am using the bitwise operator on the return value.
//build list of random dates
Random r = new Random();
var dates = new List<DateTime>();
for (int i = 0; i < 10; i++)
{
dates.Add(new DateTime(2014, r.Next(1,13), r.Next(1,28)));
}
//sort list (if you don't do this, you'll most likely get the wrong answer)
dates.Sort();
//get input
string input = "1/13/14";
DateTime inputDate = DateTime.Parse(input);
//find nearest
var result = dates.BinarySearch(inputDate);
DateTime nearest;
//get match or next in list.
if(result >= 0)
nearest = dates[result];
else if (~result == dates.Count )
nearest =dates.Last();
else
nearest = dates[~result];
If you need to find the true closest, use this in place of the last if
block.
//get match, or true nearest date in list
if(result >= 0) //date was found! Use that index.
nearest = dates[result];
else if (~result == 0) //date not found, smaller than any item in the list. use first index.
nearest = dates.First();
else if(~result == dates.Count) //date was not found, and is greater than all items. Use last index.
nearest = dates.Last();
else //date not found, somewhere in the middle of the list. find the nearest date
{
var daysAfter = dates[~result].Subtract(inputDate); //date after input
var daysBefore = inputDate.Subtract(dates[~result - 1]); //date before input
if(daysAfter < daysBefore)
nearest = dates[~result];
else
nearest = dates[~result - 1];
}