(C#) 하루 중 사용되지 않은 빈 시간대 찾기

emptyTimeRange

위 그림과 같이 하루 24시간 중 빈 시간대(예. 장비가 돌아가지 않은 시간)를 어떻게 구할수 있을까요?

시작 시간과 종료 시간의 범위를 가지는 DateTimeRange Class 가 있고
이 Class List 를 통해 하루 중 비어 있는 시간대를 찾기위한 방법을 알아보겠습니다.

DateTimeRange Class 는 아래와 같습니다.

public class DateTimeRange
{
    public DateTime Start {get; set;}
    public DateTime End {get; set;}
}

사용된 시간을 담을 List와 대상 날짜 변수를 선언합니다.
<2023년 12월 29일>

// 사용된 시간을 담을 List 생성
List<DateTimeRange> timeRanges = new List<DateTimeRange>();

// 대상 날짜 지정
DateTime targetDt = new DateTime(2023, 12, 29);

사용 시간을 List에 담아줍니다.
00:00 ~ 10:30
10:22 ~ 20:48
12:32 ~ 14:50
21:10 ~ 23:30

timeRanges.Add(new DateTimeRange{Start = targetDt.AddHours(00).AddMinutes(00), End = targetDt.AddHours(10).AddMinutes(30)});
timeRanges.Add(new DateTimeRange{Start = targetDt.AddHours(10).AddMinutes(22), End = targetDt.AddHours(20).AddMinutes(48)});
timeRanges.Add(new DateTimeRange{Start = targetDt.AddHours(12).AddMinutes(32), End = targetDt.AddHours(14).AddMinutes(50)});
timeRanges.Add(new DateTimeRange{Start = targetDt.AddHours(21).AddMinutes(10), End = targetDt.AddHours(23).AddMinutes(30)});

사용시간 List를 루프를 돌리며 빈 시간대를 찾기 위한 로직을 만듭니다.

private List<DateTimeRange> GetEmptyDateTimeRanges(DateTime theTargetDt, List<DateTimeRange> theDateTimes)
{
    // 빈 시간대를 담을 변수 선언
    List<DateTimeRange> emptyRange = new List<DateTimeRange>();

    DateTime crntEndDt = theTargetDt;             // 2023-12-29 00:00
    DateTime lastEndDt = theTargetDt.AddDays(1);  // 2023-12-30 00:00

    theDateTimes.Sort((x,y) => DateTime.Compare(x.Start, y.Start));

    foreach(DateTimeRange dtr in theDateTimes)
    {
        // 최초 crntEndDt가 00:00 부터 시작하며 
        // dtr 의 시작 시간이 큰 경우 (즉 비어 있는 시간이 발견된 경우)
        // 반환 리스트에 값을 담습니다.
        if(crntEndDt < dtr.Start)
        {
            emptyRange.Add(new DateTimeRange{Start = crntEndDt, End = dtr.Start});

            // 다음 시간대 체크를 위해 마지막 시간을 crntEndDt에 담아줍니다.
            crntEndDt = dtr.End;
            continue;
        }

        // 위에 로직에서 비어 있는 시간이 발견 되지 않은 경우 
        // 아래 구문이 실행되며 
        // 다음 시간대 체크를 위해 마지막 시간을 crntEndDt에 담아줍니다.
        if(crntEndDt < dtr.End)
            crntEndDt = dtr.End;
    }

    // 루프가 다 돌고 난 이후 2023-12-30 00:00 사이에 빈 시간을 체크합니다.
    if(crntEndDt < lastEndDt)
    {
        emptyRange.Add(new DateTimeRange{Start = crntEndDt, End = lastEndDt});
    }

    return emptyRange;


}

원하는 출력 값은 아래와 같습니다.
20:48 ~ 21:10
23:30 ~ 24:00

실제로 해당 출력 값이 나오는지 함수를 호출해서 확인해봅니다.

emptyTimeRange

정상적으로 출력된것을 확인하였습니다.