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。
对于一周中的一天,用户可以输入任意多个时间段(工作或非工作)。
将其添加并存储到数据库不是问题。
问题是在预览期间向用户显示时间段。
例如用户输入:
- 9:00-12:00工作时间
- 10:00-11:00非工作时间
- 14:00-17:00工作时间
- 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; }
}
我有一个一周中每一天的对象列表,其中存储了一周中每一天的工作时间和非工作时间。
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。 对于一周中的一天,用户可以输入任意多个时间段(工作或非工作)。 将其添加并存储到数据库不是问题。
问题是在预览期间向用户显示时间段。
例如用户输入:
- 9:00-12:00工作时间
- 10:00-11:00非工作时间
- 14:00-17:00工作时间
- 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; }
}