Неактивный интервал дня в TimeSpan - PullRequest
0 голосов
/ 05 ноября 2018

У меня есть класс c # с именем Slot, который принимает значения только от 0:00:00 до 1.00:00:00 для всех его TimeSpan свойств.

public class Slot
{
    public TimeSpan StartTime { get; set; }

    public TimeSpan EndTime { get; set; }

}

В качестве активных интервалов у меня есть эти значения, которые не перекрывают друг друга:

var activeIntervals= new List<Slot>
{
    new Slot
    {
        StartTime = new TimeSpan(10,0,0),
        EndTime = new TimeSpan(12,0,0),
    },
    new Slot
    {
        StartTime = new TimeSpan(12,0,0),
        EndTime = new TimeSpan(13,0,0),
    },
    new Slot
    {
        StartTime = new TimeSpan(16,0,0),
        EndTime = new TimeSpan(22,0,0),
    }
};

Есть ли логика для получения других интервалов дня в качестве inactiveIntervals?

В этом случае я хочу этот результат: 0:00:00 до 10:00:00, 13:00:00 до 16:00:00 и 22:00:00 до 1.00:00:00

Ответы [ 3 ]

0 голосов
/ 05 ноября 2018

Одна идея с linq:

var inactiveIntervals = activeIntervals
    .Zip(activeIntervals.Skip(1), (first, second) => {
        if (second.StartTime - first.EndTime != TimeSpan.Zero) // Get rid of regions that don't have 'gap', e.g. 12:00:00 to 12:00:00
            return new Slot { StartTime = first.EndTime, EndTime = second.StartTime };
        return null;
    }).Where(a => a != null).ToList(); // Filter out nulls

// Insert range from start to first date
inactiveIntervals.Insert(0, new Slot { StartTime = TimeSpan.Zero, EndTime = activeIntervals[0].StartTime });
// Insert range from last date to end
inactiveIntervals.Add(new Slot { StartTime = activeIntervals.Last().EndTime, EndTime = new TimeSpan(1, 0, 0, 0) });

Здесь используется трюк с .Zip, когда вы берете список, а затем архивируете его с тем же списком, перемещенным на 1. Затем вы можете сравнить EndTime из одного элемента с StartTime из следующего элемента.

Фильтрация областей без пробелов выглядит некрасиво. Вы должны проверить крайние случаи.

0 голосов
/ 05 ноября 2018

Вам необходимо создать новый экземпляр List<Slot>, а затем добавить интервалы дня, которых нет в списке activeIntervals, с помощью итерации элементов списка.

public static class SlotExtensions
{
    public static List<Slot> GetInactive(this List<Slot> slots)
    {
        Slot day = new Slot
        {
            StartTime = new TimeSpan(0,0,0),
            EndTime = new TimeSpan(24,0,0)
        }
        List<Slot> inactive = new List<Slot>();
        Slot tmp;
        foreach(Slot slot in slots)
        {
            if(day.StartTime < slot.StartTime)
            {
                tmp = new Slot
                {
                    StartTime = day.StartTime;
                    EndTime = slot.StartTime;
                };
                inactive.Add(tmp);
            };
            day.StartTime = slot.EndTime;
        }
        if(day.StartTime < day.EndTime)
        {
            inactive.Add(day);
        }
        return inactive;
    }
}

Метод расширения использует day, то есть экземпляр класса Slot и подходит для полного дня. Затем мы добавляем разницу между запусками day и повторяющегося слота в новый список, а затем переносим начало day в конец повторяющегося слота. Когда цикл завершен, метод добавляет оставшийся интервал в список.

0 голосов
/ 05 ноября 2018

Попробуйте ниже логики. Это будет работать для вас.

Вы можете проверить это здесь

var activeIntervals = new List<Slot>
{
    new Slot
    {
        StartTime = new TimeSpan(10,0,0),
        EndTime = new TimeSpan(12,0,0),
    },
    new Slot
    {
        StartTime = new TimeSpan(12,0,0),
        EndTime = new TimeSpan(13,0,0),
    },
    new Slot
    {
        StartTime = new TimeSpan(16,0,0),
        EndTime = new TimeSpan(22,0,0),
    }
};


activeIntervals = activeIntervals.OrderBy(x => x.StartTime).ToList();

var inActiveIntervals = new List<Slot>();
TimeSpan start =  new TimeSpan(0,0,0);
TimeSpan end =  new TimeSpan(24,0,0);

for (int i = 0; i < activeIntervals.Count(); i++)
{
    if (start < activeIntervals[i].StartTime) 
    {
        inActiveIntervals.Add(new Slot { StartTime = start, EndTime = activeIntervals[i].StartTime });
    }
    start = activeIntervals[i].EndTime;
}            
if (start < end) 
{
    inActiveIntervals.Add(new Slot { StartTime = start, EndTime = end });
    start = end;
}
for (int i = 0; i < inActiveIntervals.Count(); i++)
{
     Console.WriteLine(inActiveIntervals[i].StartTime.ToString() + " - " + inActiveIntervals[i].EndTime.ToString());
}
...