查找下一个最近的日期

时间:2014-03-05 20:16:07

标签: c# datetime datetime-format

我有一些日期当前存储为字符串列表。

例如:

List<string> dates = new List<string>();
dates.Add("1/10/14");
dates.Add("2/9/14");
dates.Add("1/15/14");
dates.Add("2/3/14");
dates.Add("2/15/14");

(日期为mm/dd/yy格式)

我会接受用户的输入(也是mm/dd/yy格式),但是作为字符串。

现在,我想在数组中找到用户输入日期后最接近的日期。

例如,如果用户输入"1/13/14",则输出应为"1/15/14"。 如果用户输入"2/5/14",则下一个最近的日期为"2/9/14"。 但是,如果用户输入的日期晚于最后一个日期(例如"3/1/14",则它将仍然返回数组中的最后一个日期"2/15/14"

我知道在某些时候你必须转换为DateTime类型,但我无法找出找到这样日期的逻辑。

4 个答案:

答案 0 :(得分:8)

List<string> dates = new List<string>();
            dates.Add("1/10/14");
            dates.Add("2/9/14");
            dates.Add("1/15/14");
            dates.Add("2/3/14");
            dates.Add("2/15/14");

            var allDates = dates.Select(DateTime.Parse).OrderBy(d=>d).ToList();
            var inputDate = DateTime.Parse("1/13/14");

            var closestDate = inputDate >= allDates.Last()
                ? allDates.Last()
                : inputDate <= allDates.First()
                    ? allDates.First()
                    : allDates.First(d => d >= inputDate);

现在我只是解析字符串,但你应该单独处理它。这是简单的简单LINQ,你可以去看看并做二分搜索。

答案 1 :(得分:3)

以下是使用二进制搜索的解决方案。

您需要有一个DateTime的列表,对此毫无疑问。没有必要将它们保留为string,如果必须,将它们解析到列表的路上。您可以使用LINQ转换列表中的所有元素,但这是您能够相互比较日期的唯一方法。

查看BinarySearch的页面,了解我在返回值上使用按位运算符的原因。

//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块。

//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];
}

答案 2 :(得分:2)

DateTime searchDate = new DateTime(2014,03,01);

var orderedDates = dates
.Select(d => DateTime.ParseExact(d, "M/d/yy", CultureInfo.InvariantCulture))
.OrderBy(d => d).ToList();

var result = orderedDates.FirstOrDefault(d => d > searchDate);
if (result == default(DateTime))
  result = orderedDates.Last();

答案 3 :(得分:2)

这样的东西?

List<string> dates   = YourListOfStringsHere() ; // list of strings in MM/dd/yyyy form.
DateTime desiredDate = new DateTime(2014,2,27) ;
DateTime foundDate   = dates
                       .Select( x => DateTime.ParseExact(x,"MM/dd/yyyy",CultureInfo.CurrentCulture))
                       .Where( x => x >= desiredDate.Date )
                       .Min()
                       ;

为什么你要将日期/时间值存储为字符串超出我的范围。加载它们时,为什么不转换它们呢?这样,他们更容易操作,你知道你有干净的数据。一切都变得简单了。