从与 DateTime.Now 相比的日期列表中查找最接近的日期

Finding closest date from a list of dates comparing to DateTime.Now

我正在尝试从 DateTime 列表 中获取最接近的日期。我想将列表中存在的 DateTime 项目与 DateTime.Now 进行比较,并获得 最近的日期

到目前为止,我尝试了:DateTime.Compare(item, DateTime.Now) 但这在 UiPath 中不起作用,因为我无法在 UiPath 中找到 DATE 类型。

您可以简单地使用差异来比较两个 DateTime,如下所示:TimeSpan interval = DateTime.Now - otherdate;。一旦你有了 TimeSpans,select 较小的

您可以使用 LINQ 以一种非最佳的方式进行,例如:

        var dates = new DateTime[]
        {
            new DateTime(2011, 5, 8),
            new DateTime(2011, 5, 9),
            new DateTime(2001, 6, 21)                
        };

        var input = new DateTime(2011, 5, 8, 13, 8, 58);
        var closest = dates
            .Select(x => new { date = x, diff = Math.Abs((x - input).Ticks)})
            .OrderBy(x => x.diff)
            .First();

        Console.WriteLine(closest.date);

输出:

5/9/2011 12:00:00 AM

用 datetime.now 减去列表中的日期时间有什么问题吗?它 returns 一个 TimeSpan 但你可以从中得到秒数(如果你想要那个精度,一直到毫秒)。如果您希望收到 DateTimes 列表中未来的日期时间,则只需取两者之差的绝对值。然后用linq点单,抢到第一个。

    public static void Main(string[] args)
    {
        var now = DateTime.Now;
        var dates = new List<DateTime> 
        { 
            new DateTime(2014, 1, 1),
            new DateTime(2015, 1, 1),
            new DateTime(2016, 1, 1),
            new DateTime(2017, 1, 1),
            new DateTime(2018, 1, 1),
            new DateTime(2019, 1, 1),
            new DateTime(2020, 1, 1),
            new DateTime(2020, 4, 30),
            new DateTime(2021, 1, 1)

        };

        var minDate = dates.OrderBy(x => Math.Abs((now - x).TotalSeconds)).First();


    }

使用 Linq,您可以 运行 解决惰性求值问题。在这种情况下,由于您正在使用时间对象和 DateTime.Now,这可能是一件非常糟糕的事情,因为 Linq 表达式可能不会评估 return 值 ,直到需要该值 由其他代码。这对您来说可能不是问题,其他用户已经针对此 post 回答了 Linq 版本。否则,像下面方法中那样经过验证的 For 循环方法将解决问题,并且 return 一个 Datetime 对象供以后使用。

public DateTime ReturnClosest(List<DateTime> dateTimes)
{
    //Establish Now for simpler code below
    var now = DateTime.Now;

    //Start by assuming the first in the list is the closest
    var closestDateToNow = dateTimes[0];

    //Set up initial interval value, accounting for dates before and after Now
    TimeSpan shortestInterval = now > dateTimes[0] ? now - dateTimes[0] : dateTimes[0] - now;

    //Loop through the rest of the list and correct closest item if appropriate
    //Note this starts at index 1, which is the SECOND value, we've evaluated the first above
    for (var i = 1; i < dateTimes.Count; i++)
    {
        TimeSpan testinterval = now > dateTimes[i] ? now - dateTimes[i] : dateTimes[i] - now;

        if(testinterval < shortestInterval)
        {
            shortestInterval = testinterval;
            closestDateToNow = dateTimes[i];
        }
    }

    //return the closest Datetime object
    return closestDateToNow;
}

使用 LINQ 的方法很简单,但 O(n*log(n)) 很复杂。 DateTime.Subtraction Operator subtracts a specified date and time from another specified date and time and returns a time interval. TimeSpan.Duration() returns a new TimeSpan object whose value is the absolute value of the current TimeSpan object. So, you an just order source value by durations and take first value with First().

DateTime closestDate = dates.OrderBy(d => (d - DateTime.Now).Duration()).First();

存在 O(n) 复杂度的解决方案:

var closestDate = (date: new DateTime(), duration: TimeSpan.MaxValue);
foreach (var date in dates)
{
    var duration = (date - DateTime.Now).Duration();
    if (duration < closestDate.duration)
        closestDate = (date, duration);
}
return closestDate.date;

你也可以对 LINQ 和 O(n) 复杂性做同样的事情,但以一种不明显的方式:

DateTime closestDate = dates
    .Select(d => (date: d, duration: (d - DateTime.Now).Duration()))
    .Aggregate((date: new DateTime(), duration: TimeSpan.MaxValue), (currentClosest, d) => d.duration < currentClosest.duration ? d : currentClosest)
    .date;