C# 时间表将工作时间显示为 9:00-13:00 之类的字符串; 14:00-18:00

C# timetable show working hours as string like 9:00-13:00; 14:00-18:00

我有一个一周中每一天的对象列表,其中存储了一周中每一天的工作时间和非工作时间。

public class Schedule
{
    public bool IsOn { get; set; }
    public DayOfWeek DayOfWeek { get; set; }
    public short TimeFrom { get; set; } // store time as amount of minutes since start of day
    public short TimeTo { get; set; } // store time as amount of minutes since start of day
}

所以我想要得到的是一周中每一天的时间范围。 例如,我们星期一有 2 件商品

new Schedule() { IsOn = true, DayOfWeek = DayOfWeek.Moday, TimeFrom = 540, TimeTo = 1080 }
new Schedule() { IsOn = false, DayOfWeek = DayOfWeek.Moday, TimeFrom = 780, TimeTo = 840 }

我需要在 UI 上显示为: 星期一:9:00-13:00; 14:00-18:00

更新

我想知道的主要是关于如何解决这种事情的算法。 如果你看一下例子 Monday: 9:00-13:00; 14:00-18:00 你会看到我只想显示工作时间。 我认为它类似于 TimeRange,但我不知道如何编码。

更新 2

为了更清楚,我将提供一个示例。 用户可以像句号一样输入程序的工作时间,例如9:00-12:00 用户也可以像句号一样输入程序的非工作时间,例如10:00-11:00。 对于一周中的一天,用户可以输入任意多个时间段(工作或非工作)。 将其添加并存储到数据库不是问题。

问题是在预览期间向用户显示时间段。

例如用户输入:

  1. 9:00-12:00工作时间
  2. 10:00-11:00非工作时间
  3. 14:00-17:00工作时间
  4. 15:00-15:30非工作时间

我需要显示所有这些,例如:

9:00-10:00; 11:00-12:00; 14:00-15:00; 15:30-17:00;

更新 3

我认为这可能与图表有关。请帮助选择算法。

以下内容应该会为您提供所需的输出。使用您提供的样本数据,这就是结果。

输出

星期一:09:00-18:00; 13:00-14:00

代码

void Main()
{
    var schedules = new[]{
        new Schedule() { IsOn = true, DayOfWeek = DayOfWeek.Monday, TimeFrom = 540, TimeTo = 1080 },
        new Schedule() { IsOn = false, DayOfWeek = DayOfWeek.Monday, TimeFrom = 780, TimeTo = 840 }
    };


    var byDay = schedules.GroupBy(i => i.DayOfWeek)
                .Select(i =>
                {
                    var times = i.Select(t => string.Format(@"{0:hh\:mm}-{1:hh\:mm}", TimeSpan.FromMinutes(t.TimeFrom), TimeSpan.FromMinutes(t.TimeTo)));
                    return string.Format("{0}: {1}", i.Key, string.Join("; ", times));
                });

    foreach (var day in byDay)
    {
        Console.WriteLine(byDay);
    }
}

public class Schedule
{
    public bool IsOn { get; set; }
    public DayOfWeek DayOfWeek { get; set; }
    public short TimeFrom { get; set; } // store time as amount of minutes since start of day
    public short TimeTo { get; set; } // store time as amount of minutes since start of day
}

终于找到解决方法了

    public static IEnumerable<Tuple<short, short>> ExcludeIntervals(IEnumerable<ISchedule> range)
    {
        var list = range
            .SelectMany(x => new[] {Tuple.Create(x.TimeFrom, x.IsOn), Tuple.Create(x.TimeTo, !x.IsOn)})
            .OrderBy(d => d.Item1).ThenBy(d => d.Item2)
            .ToList();

        var first = default(short);
        var count = 1;

        foreach (var item in list)
        {
            if (item.Item2) // false - start of unavailability interval. true - end of unavailability interval.
            {
                if (--count == 0) // Become available.
                {
                    first = item.Item1;
                }
            }
            else
            {
                if (++count == 1)
                {
                    var last = item.Item1;
                    if (last >= first) // if next unavailability starts right after previous ended, then no gap.
                    {
                        yield return Tuple.Create(first, last);
                    }
                }
            }
        }
    }

    public interface ISchedule
    {
        bool IsOn { get; set; }
        short TimeFrom { get; set; }
        short TimeTo { get; set; }
    }