我在这个算法中缺少什么来在两个TimeSpans之间找到可能跨越不同日期的TimeOfDay?

Rac*_*hel 6 .net c# timespan .net-4.0

我有List<T>24小时内的可用时间,以及两个TimeSpans,minTime和maxTime.

我需要找到内一天的时间List<T>,该之间土地minTimemaxTime,但是由于这个正在多个时区中使用时,minTime和MAXTIME可以在不同的日子和跨越像下午1点至凌晨1点,第二天

我最接近的就是这个,但我觉得我在这里缺少一些主要的组件,或者做一些非常低效的事情,因为我对这个TimeSpan对象很新.我只是无法弄清楚是什么......

// Make new TimeSpan out of maxTime to eliminate any extra days (TotalHours >= 24),
// then check if time on the MaxTime is earlier than the MinTime
if (new TimeSpan(maxTime.Hours, maxTime.Minutes, maxTime.Seconds) < minTime)
{
    // If time on MaxTime is earlier than MinTime, the two times span separate days,
    // so find first time after minTime OR before maxTime
    nextAvailableTime = Times.FirstOrDefault(p =>
        (p.Time.TimeOfDay >= minTime || (p.Time.TimeOfDay < maxTime))
        && p.Count < ConcurrentAppointments);
}
else
{
    // If time on MaxTime is later than MinTime, the two times are for the same day
    // so find first time after minTime AND before maxTime
    nextAvailableTime = Times.FirstOrDefault(p =>
        (p.Time.TimeOfDay >= minTime && p.Time.TimeOfDay < maxTime)
        && p.Count < ConcurrentAppointments);
}
Run Code Online (Sandbox Code Playgroud)

名单Times用途EST(我的本地时间),但是minTimemaxTime可以根据其他时区.

例如,如果我们为夏威夷时区运行此算法,我们将最终拥有minTime = new TimeSpan(13, 0, 0)maxTime = new TimeSpan(25, 0, 0),从早上8点 - 晚上8点HST =下午1点 - 美国东部时间凌晨1点.

Times集合是一个List<AppointmentTime>,并且AppointmentTime是一个类如下:

class AppointmentTime
{
    DateTime Time { get; set; } 
    int Count { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我相当肯定,我失去了一些东西主要这里,还是应该有这样做的,我是不知道的更有效的方式,但我真的不认为它可能是什么.我的算法有问题吗?或者更有效的方法来找到可能跨越不同日子的TimeOfDay两者之间TimeSpans

更新

根据CasperOne的回答,我想出了我所缺少的东西.我忘了日期确实很重要,因为我的时间跨越不同的时区.

使用我上面的夏威夷时区示例,安排星期一的约会将导致在周日晚上错误地安排夏威夷约会.

我的解决方案是在为24小时工作日的"第一个窗口"安排约会之前检查前一天是否有效,并.AddDays(maxTime.Days)在与之比较时调整约会日期maxTime

// If time on MaxTime is earlier than MinTime, the two times span separate days,
// so find first time after minTime OR before maxTime if previous day has appointments set as well
var isPreviousDayValid = IsValidDate(AppointmentDate.AddDays(-1));

nextAvailableTime = Times.FirstOrDefault(p =>
    (p.Time.TimeOfDay >= minTime 
        || (p.Time.AddDays(maxTime.Days).TimeOfDay < maxTime && isPreviousDayValid)
    ) && p.Count < ConcurrentAppointments);
Run Code Online (Sandbox Code Playgroud)

cas*_*One 1

总的想法是,不要比较时间,要比较日期;将您的窗口从时间转换为日期,其余的就很容易了。

您可以为列表中的每个DateTime项目生成一组新的实例,以比较最小值和最大值,并使用该属性作为计算要比较的范围上限的基础。Date

这假设您的minTime始终小于maxTime,并且如果您的窗口覆盖超过一天,则通过在 上具有大于 24 小时的Hours属性值来表示重叠到新一天的范围。TimeSpan

你必须看看前一天和后天是否有一个窗口。例如:

   (1)  (2)  (3)  (4)  (5)
----x----x----x----x----x----

(1) - 1/1/1900 11:00 PM - Date component in your list - 1 day + min time
(2) - 1/2/1900 12:05 AM - this is the date and time from your list
(3) - 1/2/1900 01:00 AM - Date component in your list - 1 day + max time
(4) - 1/2/1900 11:00 PM - Date component in your list + min time
(5) - 1/3/1900 01:00 AM - Date component in your list + max time
Run Code Online (Sandbox Code Playgroud)

这意味着您需要创建两个窗口并检查是否位于以下任一窗口中:

nextAvailableTime = Times.FirstOrDefault(p => {
    // Check count first, get this out of the way.
    if (!(p.Count < ConcurrentAppointments)) return false;

    // The date time and the date component
    DateTime dt = p.Time;
    DateTime d = dt.Date;

    // The windows
    DateTime prevWindowMin = d.AddDays(-1) + minTime;
    DateTime prevWindowMax = d.AddDays(-1) + maxTime;
    DateTime windowMin = d + minTime;
    DateTime windowMax = d + maxTime;

    // Is it in *either* window;
    return
        (prevWindowMin <= dt && dt <= prevWindowMax)||
        (windowMin <= dt && dt <= windowMax);
});
Run Code Online (Sandbox Code Playgroud)

从您的问题中尚不完全清楚,但是如果一天中的时间不是列表Date中项目的组成部分,您可以替换该p.Time日期Date组成部分(根据需要减去一天来创建窗口),并且它应该工作。