按工作时间计算请假时长

            // 需求:根据考勤管理计算请假时长
            // 1.考勤管理 包含工作日 + 节假日设置
            // 举例
            // 周一至周五 上班时间 9:00 - 18:00 中午休息时间 12:00 - 13:30  (实际工作时间长是7.5 如果请假 肯定也是请假时长7.5小时)
            // 节假日设置 10-1 至 10-7 为国庆节 节假日
            // 问题请假时间范围为 2022-9-28 10:35 至 2022-10:9:14:35 的请假时长为多少分钟 


            // 先来看一个简单示例  今天上班时间为 9-18点 休息时间 12-13点休息 
            // 请假时间 为8点到15点

            // 工作时间集合 设为集合A
            var A = new List<int> { 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 };

            // 请假时间集合 设为集合B
            var B = new List<int> { 8, 9, 10, 11, 12, 13, 14, 15 };

            // 休息时间集合 设为集合C
            var C = new List<int> { 12, 13, 17 };

            // 首先请假时间长集合必须是在工作时间(A)和请假时间集合(C)之间由此可得到(A∩B) 意思是A集合和B集合的交集
            // 因为存在休息时间所以必须排除休息时间集合(C) 则可得到(A∩B)-C  意思是(A交B)差C 白话文就是 先求A和B的交集D 在求D和C的差集 

            // A∩B ={9, 10, 11, 12, 13, 14, 15} 
            // A∩B-C ={9, 10, 11, 14, 15}

            // 转化成代码
            var collection = A.Intersect(B).Except(C);
            // 得到请假时长就是结果求总条数
            var leaveTime = collection.Count();
            // 输出结果5小时

            // 在回过头计算 请假时间范围为 2022-9-28 10:35 至 2022-10:9:14:35 的请假时长为多少分钟 
            DateTime leaveTimeStart = new(2022, 09, 28, 10, 35, 00), leaveTimeEnd = new(2022, 10, 10, 14, 35, 00);
            // 得到开始请假时间集合
            var b = GetDateTimeMinutes(leaveTimeStart, leaveTimeEnd);

            // 节假日集合
            var holidays = new List<DateTime>
            {
                new(2022, 10, 1),
                new(2022, 10, 2),
                new(2022, 10, 3),
                new(2022, 10, 4),
                new(2022, 10, 5),
                new(2022, 10, 6),
                new(2022, 10, 7)
            };

            // 周末 周六 周日
            var workDays = new List<DayOfWeek>
            {
                DayOfWeek.Sunday,
                DayOfWeek.Saturday,
            };

            // 工作时间集合
            var a = new List<DateTime>();

            // 休息时间集合
            var c = new List<DateTime>();

            // 总共请假的天数有那些
            var dates = GetDateTimes(leaveTimeStart, leaveTimeEnd);
            foreach (var date in dates)
            {
                // 如果是节假日则排除不计算请假时长
                if (holidays.Any(d => d == date.Date))
                {
                    continue;
                }

                // 如果是周末则排除不计算请假时长
                if (workDays.Any(d => d == date.DayOfWeek))
                {
                    continue;
                }

                // 工作时间
                var startWork = new DateTime(date.Year, date.Month, date.Day, 9, 0, 0);
                var endWork = new DateTime(date.Year, date.Month, date.Day, 18, 0, 0);
                a.AddRange(GetDateTimeMinutes(startWork, endWork));

                // 休息时间
                var startRest = new DateTime(date.Year, date.Month, date.Day, 12, 0, 0);
                var endRest = new DateTime(date.Year, date.Month, date.Day, 13, 30, 0);
                c.AddRange(GetDateTimeMinutes(startRest, endRest));
            }

            // 得到请假分钟结果
            var leaveMinutes = a.Intersect(b).Except(c).Count();

            //请假时长 结果1500分钟
            /* 2022-9-28  10:35  355分钟  这天为工作日请假时间为10:30到18:00 排除休息时间 355分钟
             * 2022-9-29         450分钟  这天为工作日请假时间为09:00到18:00 排除休息时间 450分钟
             * 2022-9-30         450分钟  这天为工作日请假时间为09:00到18:00 排除休息时间 450分钟
             * 2022-10-11 14:35  245分钟  这天为工作日请假时间为09:00到14:35 排除休息时间 245分钟
             * 结果 1500分钟 
            */

工具方法

/// <summary>
        /// 计算两个时间之间的分钟日期
        /// </summary>
        /// <param name="startDate">开始日期</param>
        /// <param name="endDate">结束日期</param>
        /// <returns>日期集合</returns>
        /// <exception cref="ArgumentException">异常</exception>
        public static IEnumerable<DateTime> GetDateTimeMinutes(DateTime startDate, DateTime endDate)
        {
            if (endDate < startDate)
            {
                throw new ArgumentException(nameof(startDate));
            }

            var result = new List<DateTime>();
            for (var date = startDate; date < endDate; date = date.AddMinutes(1))
            {
                result.Add(date);
            }

            return result;
        }

        /// <summary>
        /// 计算两个时间之间的日期
        /// </summary>
        /// <param name="startDate">开始日期</param>
        /// <param name="endDate">结束日期</param>
        /// <returns>日期集合</returns>
        /// <exception cref="ArgumentException">异常</exception>
        public static IEnumerable<DateTime> GetDateTimes(DateTime startDate, DateTime endDate)
        {
            if (endDate < startDate)
            {
                throw new ArgumentException(nameof(startDate));
            }

            var result = new List<DateTime>();
            for (var date = startDate; date <= endDate; date = date.AddDays(1))
            {
                result.Add(date);
            }

            return result;
        }

 

posted @ 2022-10-26 14:27  刘小吉  阅读(616)  评论(0编辑  收藏  举报