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

于是,要返回生活习惯上的天数间隔,必须要忽略掉时间,只以日期(年、月、日)计算。

posted @ 2010-08-13 21:38  ambar  阅读(1239)  评论(0编辑  收藏  举报