Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在这个算法中,在两个可能跨越不同天的时间跨度之间找到一个TimeOfDay,我遗漏了什么?_C#_.net_.net 4.0_Timespan - Fatal编程技术网

C# 在这个算法中,在两个可能跨越不同天的时间跨度之间找到一个TimeOfDay,我遗漏了什么?

C# 在这个算法中,在两个可能跨越不同天的时间跨度之间找到一个TimeOfDay,我遗漏了什么?,c#,.net,.net-4.0,timespan,C#,.net,.net 4.0,Timespan,我有一个24小时内可用时间的列表,以及两个时间跨度,minTime和maxTime 我需要在列表中找到一天中位于minTime和maxTime之间的时间,但是由于这在多个时区中使用,minTime和maxTime可以在不同的日子中,时间跨度大约为下午1点到次日凌晨1点 我最近接触到的是这个,但我觉得这里缺少了一些主要组件,或者做了一些非常低效的事情,因为我对TimeSpan对象相当陌生。我只是不知道是什么 // Make new TimeSpan out of maxTime to elimin

我有一个24小时内可用时间的
列表
,以及两个
时间跨度
,minTime和maxTime

我需要在
列表中找到一天中位于
minTime
maxTime
之间的时间,但是由于这在多个时区中使用,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);
}
我相当肯定我在这里遗漏了一些重要的东西,或者应该有一种更有效的方法来做这件事,我不知道,但我真的想不出它可能是什么。我的算法有问题吗?或者更有效地在两个可能跨越不同天的
时间跨度
之间查找
时间间隔

更新

我根据我的经验找出了我遗漏的东西。我忘了日期其实很重要,因为我的时间跨越不同的时区

以我上面的夏威夷时区为例,安排周一的约会会导致错误地安排周日晚上的夏威夷约会

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

// 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);
//如果MaxTime上的时间早于MinTime,则这两个时间跨越不同的天,
//所以,如果前一天也有预约,那么在minTime之后或maxTime之前找到第一次
var isPreviousDayValid=IsValidDate(任命日期.AddDays(-1));
nextAvailableTime=Times.FirstOrDefault(p=>
(p.Time.TimeOfDay>=minTime
||(p.Time.AddDays(maxTime.Days).TimeOfDay
总体思路是,不要比较时间,要比较日期;把你的窗口从时间转换成日期,剩下的就很容易了

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

这假设您的
minTime
始终小于
maxTime
,并且如果您通过在上有一个值来表示重叠到新一天的范围

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

   (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
这意味着您需要创建两个窗口,并检查是否存在以下任一窗口:

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);
});
nextAvailableTime=Times.FirstOrDefault(p=>{
//先检查一下计数,把这个让开。
如果(!(p.Count(prevWindowMin@Rachel,你能提供一个反例,说明这是无法使用的吗

nextAvailableTime = Times.OrderBy(i => i.Time).FirstOrDefault(i => i.Count < ConcurrentAppointments &&
    i.Time.TimeOfDay >= minTime &&
    i.Time.TimeOfDay < maxTime
            );

@pst“最有效”?:)我有一个我认为有效的解决方案…我只是觉得它没有优化,还有一个更好的方法我错过了,因为我对
TimeSpan
objectBetter:)相当不熟悉我将把标题放在技术上。如果
minDate
大于
maxDate
,我们可以假设它表示两天的时间窗口吗?@casperOne
minDate
永远不会大于
maxDate
,但是
minDate.Hours
可以大于
maxDate.Hours
,在这种情况下是的uld表示超过一天的时间窗口是
minDate
maxDate
DateTime
结构和实际日期组件,或者其中的日期不相关?如果
minTime
大于
maxTime
,则表示窗口在第二天?这在cas中不起作用e其中minTime和maxTime结束于两个不同的日期,例如
minTime=new TimeSpan(13,0,0)
maxTime=new TimeSpan(25,0,0)
(东部标准时间上午8点到晚上8点->UTC下午1点到凌晨1点)@Rachel,谢谢你的反馈。你觉得我的更新怎么样?谢谢你更新的答案,但是我意识到我没有检查算法中的日期,没有遗漏我的实际语法。很抱歉这个令人困惑的问题,我把它归咎于这是一个漫长的一周结束时的一个星期五,我的大脑感到兴奋:)我知道我做错了什么,但我不知道这与我使用的语法(而不是算法本身)有什么关系。谢谢,我明天必须运行一些测试来确保这一点,看看它与我当前的方法相比如何,但你的逻辑似乎是正确的。(这是为了从所有不同的时区一次安排数千个约会,所以性能对我来说很重要)@Rachel看到最后一段(你可能错过了);如果是其他日期,你可以得到
date
组件并使用它(我想象你真正拥有的)。这意味着您不必每次都计算最小和最大
DateTime
窗口。不管怎样,在任何一台像样的机器上,这些操作都应该是微不足道的,即使是数千件物品。@rachel我必须意识到这是1/2。如果要解决这个问题,您还必须使用前一天(因为您的时间可能与前一天重叠).也就是说,只需使用当前日期和之前的日期作为基础,然后检查betwe
nextAvailableTime = Times.OrderBy(i => i.Time).FirstOrDefault(i => i.Count < ConcurrentAppointments &&
    i.Time.TimeOfDay >= minTime &&
    i.Time.TimeOfDay < maxTime
            );
var Times = new List<AppointmentTime>();
var ConcurrentAppointments = 10;
Times.AddRange(new[]{
    new AppointmentTime()
    {
        Count = 0,
        Time = new DateTime(2012, 12, 1, 1, 30, 0)
    },
    new AppointmentTime()
    {
        Count = 0,
        Time = new DateTime(2012, 12, 1, 13, 5, 0)
    },
    new AppointmentTime()
    {
        Count = 0,
        Time = new DateTime(2012, 12, 1, 11, 0, 0)
    }});

var minTime = new TimeSpan(13, 0, 0);
var maxTime = new TimeSpan(25, 0, 0);

// Version 1
// Not so performant, ~0.48 seconds for a loop of 1,000,000 iterations, see Version 2

//nextAvailableTime = Times.OrderBy(i => i.Time).FirstOrDefault(i => i.Count < ConcurrentAppointments &&
//    i.Time.TimeOfDay.TotalSeconds >= Math.Min(maxTime.TotalSeconds % (3600 * 24), minTime.TotalSeconds)
//    );

// Version 2
// Better performance, ~0.12 seconds for 1,000,000 iterations. We calculate the 
// constant value we are comparing with outside the lambda expression

// We calculate the `totalSeconds` variable as the minimum of seconds within the 
// 24h day. For that, we use the `% (3600 * 24)` operation to exclude the days.
var totalSeconds = (int)Math.Min(maxTime.TotalSeconds % (3600 * 24), minTime.TotalSeconds);

// We create a timespan variable called `timeOfDay` which is based on the
// `totalSeconds` variable above. Note that the day is not essential.
var timeOfDay = (new DateTime(1, 1, 1, totalSeconds / 3600, (totalSeconds % 3600) / 60, totalSeconds % 60)).TimeOfDay;

// Returns the `AppointmentTime` with the 01:30 AM. Note, again, that the 
// date of the `AppointmentTime` is not essential
nextAvailableTime = Times.FirstOrDefault(i => i.Count < ConcurrentAppointments &&
                i.Time.TimeOfDay >= timeOfDay
                );