LINQ集合操作——计算工作时间
如何计算两个时间段的有效工作时间?比如("2010-08-10 9:00")和("2010-08-11 16:00")之间?
下面是刚刚得到的,没有考虑周末:
public static int CalcWorkingHours(DateTime begin, DateTime end)
{
if (begin > end) return 0;
// 忽略TimeSpan计算时的时间
Func<DateTime, DateTime> ignoreTime = dt => new DateTime(dt.Year, dt.Month, dt.Day);
// 时间段的集合
Func<int, int, IEnumerable<int>> timeSet = (min, max) => Enumerable.Range(min, max - min);
var days = (ignoreTime(end) - ignoreTime(begin)).Days;
// 工作时间段
var wh = timeSet(8, 12).Union(timeSet(14, 18));
var hours =
days == 0 //是否是当天
? timeSet(begin.Hour, end.Hour).Intersect(wh).Count()
: timeSet(begin.Hour, 24).Intersect(wh).Count() + timeSet(0, end.Hour).Intersect(wh).Count();
return (days - 1) * wh.Count() + hours;
}
网上有人问到这个有意思的问题,下班之后在公交车上想到了LINQ的做法。
工作时间的计算是上午4小时和下午4小时的并集。然后就简单了,有效工作时间就是全天某个时间段和工作时间两个序列的交集。
PS: C#中的TimeSpan计算有个要注意的地方,比如:
var begin = DateTime.Parse("2010-08-10 20:00");
var end = DateTime.Parse("2010-08-11 16:00");
Console.WriteLine((end - begin).Days); // 输出:0
Console.WriteLine((end - begin).TotalDays); // 输出:0.916666666666667
于是,要返回生活习惯上的天数间隔,必须要忽略掉时间,只以日期(年、月、日)计算。