起始时间和持续时间与时隙合并
本文关键字:时隙 合并 持续时间 时间 | 更新日期: 2023-09-27 18:09:01
我有一个包含几个电视广播的数据文件,它们的开始和持续时间以分钟为单位,我必须将它与另一个包含大约2小时时间段的文件合并。下面是它的样例:
File1:
- 日期|开始|持续时间
- 19/05/2014 | 15:25:00 | 55
- 19/05/2014 | 16:20:00 | 30
- 19/05/2014 | 16:50:00 | 25
- 19/05/2014 | 17:15:00 | 55
- 19/05/2014 | 18:10:00 | 30
File2:
- 时隙| timeslot_info
- 05:00 - 07:00|info_to_merge
- 07:00 - 09:00|info_to_merge
- 09:00 - 11:00|info_to_merge
- 11:00 - 13:00|info_to_merge
- 13:00 - 15:00|info_to_merge
- 15:00 - 17:00|info_to_merge
- 17:00 - 19:00|info_to_merge
- 19:00 - 21:00|info_to_merge
- 21:00 - 23:00|info_to_merge
- 23:00 - 25:00|info_to_merge
- 25:00 - 27:00|info_to_merge
- 27:00 - 29:00|info_to_merge
现在我要做的是,对于文件1的每次出现,根据这些规则找到文件2对应的时间段:—必须选择事件"包含最多"的时间段—如果事件完全覆盖多个时隙,则应选择最后一个完全覆盖的时隙
我已经尝试了很多繁重的代码,但我找不到如何推断正确的时隙。我想到了一个逻辑,我正在浏览第一个文件的每次出现,并尝试为其分配一个时隙键,以便进一步匹配,但没有更多:
private string GetTimeSlot(string line)
{
string result = "";
string[] tab = line.Split(''t');
string start = tab[LogsStartTimeColumnIndex];
string[] starttab = start.Split(':');
TimeSpan StartTime = new TimeSpan(Int32.Parse(starttab[0]), Int32.Parse(starttab[1]), Int32.Parse(starttab[2]));
TimeSpan Duration = new TimeSpan(0, Int32.Parse(tab[LogsDurationColumnIndex], 0), 0);
TimeSpan EndTime = StartTime + Duration;
//don't know how to do it from here..
return result;
}
我的方法是将输入数据文件的解析与找到所需Timeslot的逻辑分开。
根据查找正确Timeslot的逻辑,您可以使用以下代码作为开始。它实现了你在上面详细说明的逻辑,即"必须选择事件"最多包含"的时隙-如果事件完全覆盖多个时隙,则应选择最后一个完全覆盖的时隙":
UPDATED -为了支持'night'时隙我引入了一个TimeInHours
类来表示Timespan
之前在做什么
public class TimeslotsFinder
{
private readonly IEnumerable<Timeslot> _allTimeslots;
public TimeslotsFinder(IEnumerable<Timeslot> allTimeslots)
{
_allTimeslots = allTimeslots;
}
public Timeslot FindTimeslot(Broadcast broadcast)
{
var found = _allTimeslots
.Select(t => new { Timeslot = t, DurationInTimeslot = DurationInTimeslot(broadcast, t) })
.Where(x => x.DurationInTimeslot > TimeInHours.Zero)
.OrderByDescending(x => x.DurationInTimeslot.Value)
.ThenByDescending(x => x.Timeslot.Start.Value)
.FirstOrDefault();
return found == null ? null : found.Timeslot;
}
private static TimeInHours DurationInTimeslot(Broadcast broadcast, Timeslot timeslot)
{
if (!(InTimeslot(broadcast, timeslot) || CoversEntireTimeslot(broadcast, timeslot))) return TimeInHours.Zero;
var endToUse = broadcast.EndTime >= timeslot.End
? timeslot.End
: broadcast.EndTime;
var startToUse = broadcast.StartTime <= timeslot.Start
? timeslot.Start
: broadcast.StartTime;
return endToUse.Subtract(startToUse);
}
private static bool InTimeslot(Broadcast broadcast, Timeslot timeslot)
{
var startsInTimeslot = timeslot.Start <= broadcast.StartTime && broadcast.StartTime < timeslot.End;
var endsInTimeslot = timeslot.End < broadcast.EndTime && broadcast.EndTime <= timeslot.End;
return startsInTimeslot || endsInTimeslot;
}
private static bool CoversEntireTimeslot(Broadcast broadcast, Timeslot timeslot)
{
return broadcast.StartTime <= timeslot.Start && broadcast.EndTime >= timeslot.End;
}
}
上面的逻辑显然使用了这些类:
这些也被更新为使用TimeInHours类
public class Broadcast
{
public DateTime StartDateTime { get; set; }
public TimeSpan Duration { get; set; }
public TimeInHours StartTime
{
get
{
return TimeInHours.FromTimeSpan(StartDateTime.TimeOfDay);
}
}
public TimeInHours EndTime
{
get
{
return TimeInHours.FromTimeSpan(StartDateTime.Add(Duration).TimeOfDay);
}
}
}
public class Timeslot
{
public TimeInHours Start { get; set; }
public TimeInHours End { get; set; }
public TimeInHours Duration
{
get
{
return End.Subtract(Start);
}
}
}
public class TimeInHours
{
public TimeInHours(int value)
{
Value = value;
}
public int Value { get; private set; }
public TimeInHours Subtract(TimeInHours x)
{
return new TimeInHours(Value - x.Value);
}
public static TimeInHours FromTimeSpan(TimeSpan ts)
{
return new TimeInHours(ts.Hours);
}
public static TimeInHours Zero
{
get
{
return new TimeInHours(0);
}
}
public static bool operator < (TimeInHours t1, TimeInHours t2)
{
return t1.Value < t2.Value;
}
public static bool operator >(TimeInHours t1, TimeInHours t2)
{
return t1.Value > t2.Value;
}
public static bool operator <=(TimeInHours t1, TimeInHours t2)
{
return t1.Value <= t2.Value;
}
public static bool operator >=(TimeInHours t1, TimeInHours t2)
{
return t1.Value >= t2.Value;
}
}
你可以这样测试这个逻辑:
也更新为使用TimeInHours类
var timeslots = new List<Timeslot>
{
new Timeslot{Start = new TimeInHours(5), End = new TimeInHours(7)},
new Timeslot{Start = new TimeInHours(7), End = new TimeInHours(9)},
new Timeslot{Start = new TimeInHours(9), End = new TimeInHours(11)},
new Timeslot{Start = new TimeInHours(11), End = new TimeInHours(13)},
new Timeslot{Start = new TimeInHours(13), End = new TimeInHours(15)},
new Timeslot{Start = new TimeInHours(15), End = new TimeInHours(17)},
new Timeslot{Start = new TimeInHours(17), End = new TimeInHours(19)},
new Timeslot{Start = new TimeInHours(19), End = new TimeInHours(21)},
new Timeslot{Start = new TimeInHours(21), End = new TimeInHours(23)},
new Timeslot{Start = new TimeInHours(23), End = new TimeInHours(25)},
};
var finder = new TimeslotsFinder(timeslots);
var broadcast = new Broadcast { StartDateTime = DateTime.Parse("19/05/2014 09:00"), Duration = TimeSpan.FromMinutes(250) };
var timeslot = finder.FindTimeslot(broadcast);
有了这个逻辑,接下来就只需要解析数据文件来创建所需的Broadcast
和Timeslot
实例。我将把这部分留给您,因为我相信您自己创建解析代码将对您有益。