首页 > 代码库 > 启明星请假系统里,计算工作日的实现

启明星请假系统里,计算工作日的实现

启明星新版增加系统,增加了请假时长的自动计算。本文讨论请假系统算法的实现。(如果您有好的算法,欢迎和我联系。)

在请假前,我们假定,公司的工作时间是 上午:8:00--12:00 下午13:00--17:00。 中间一个小时是午饭时间。

(1)首先考虑当天请假情况,例如今天是2014-6-25日。

   假设用户请假是从  2014-6-25 9:00:00 到 2014-6-25 16:00:00

那么,如果人工算的话,应该是分为两端:

(a)计算 9:00--12:00的时段(3个小时)

(b)计算13:00--16:00的时段(3个小时)

 也就是,用户其实请假是3+3 共6个小时。

  但是用户请假时间是任意选择的,他可能选择从7:00--16:00,那么7:00--8:00这一个小时,是不算请假的。

如果我们把用户的请假时代用AB表示,作息上午时间用CD表示,作息下午时间用EF表示

那么一天的请假其实是计算2个时间段的交集,也就是请假时长= AB∩CD+AB∩EF 

下面考虑AB∩CD也就是求2个时间段的交集,这需要考虑六种情况:(具体略,高中高数求集合交集时常用的方法。)

为此,我们可以写出一个方法:Get2TimeSpan 获取2个时间段有多长(单位为分钟。)

        private double Get2TimeSpan(DateTime dt1, DateTime dt2, DateTime dt3, DateTime dt4)        {            //1.            if (dt4 <= dt1)                return 0;            //2.            if (dt3 >= dt2)                return 0;            //3             if (dt1 >= dt3 && dt1 <= dt4 && dt4 <= dt2)                return (dt4 - dt1).TotalMinutes;            //4            if (dt1 <= dt3 && dt3 <= dt2 && dt2 <= dt4)                return (dt2 - dt3).TotalMinutes;            //5            if (dt1 <= dt3 && dt4 <= dt2)                return (dt4 - dt3).TotalMinutes;            return (dt2 - dt1).TotalMinutes;        }


上面的方法是2个时间的交集,一天其实是分上午和下午,共2个,所以我们可以写一个获取一天内,交集多长的函数

        public double GetSameDayTimeSpan(DateTime dt1, DateTime dt2, DateTime base1, DateTime base2, DateTime base3, DateTime base4, DataTable table)        {            if (isWorkDay(dt1, table))            {                return Get2TimeSpan(dt1, dt2, base1, base2) + Get2TimeSpan(dt1, dt2, base3, base4);            }            else            {                return 0;            }        }


这样,我们就可以获取,一天内,用户请假时长的放上。

 

 

(2)请假跨天的情况

   请假跨天时,我们需要知道每一天是否是工作日。 这里,是不是工作日并不完全是否是周六或者周日决定,因为例如国庆节10.1日,不管是否是工作日,都放假的。

所以,我们需要判断一个工作日是否是工作日:

   public bool isWorkDay(DateTime dt, DataTable  table)        {            bool isworkday = false;            DataView dv = table.DefaultView;            dv.RowFilter = " sdate=#" + dt.ToString("yyyy-MM-dd") + "#";            if (dv.Count > 0)            {                isworkday = dv[0]["isworkday"].ToString() == "1" ? true : false;                return isworkday;            }            if (dt.DayOfWeek == DayOfWeek.Saturday || dt.DayOfWeek == DayOfWeek.Sunday)            {                return false;            }            return true;        }

这里,以用户自定义的日期优先级最高。如果不存在用户自定义的,则自动使用默认的日期。

在启明星请假系统里,是一天天的进行判断跨天请假的,如果是工作日,直接返回当天时长,否则返回为0

int day = (odt2 - odt1).Days;                                       for (int i = 0; i <= day; i++)                   {                       if (i == 0)                       {                           _base = odt1.AddDays(i).ToString("yyyy-MM-dd");                           base1 = DateTime.Parse(_base + " " + dtfrom1);                           base2 = DateTime.Parse(_base + " " + dtto1);                           base3 = DateTime.Parse(_base + " " + dtfrom2);                           base4 = DateTime.Parse(_base + " " + dtto2);                           tdt = base4;                           totalMiniter+= GetSameDayTimeSpan(odt1, tdt, base1, base2, base3, base4, table2);                       }                       else                       {                           if (i == day)                           {                               //最后一天                            _base = odt1.AddDays(i).ToString("yyyy-MM-dd");                           base1 = DateTime.Parse(_base + " " + dtfrom1);                           base2 = DateTime.Parse(_base + " " + dtto1);                           base3 = DateTime.Parse(_base + " " + dtfrom2);                           base4 = DateTime.Parse(_base + " " + dtto2);                           tdt = base1;                           totalMiniter+= GetSameDayTimeSpan(base1, odt2, base1, base2, base3, base4, table2);                                            }                           else                           {                               tdt = odt1.AddDays(i);                               if (isWorkDay(tdt, table2))                               {                                   totalMiniter += workDayTotalMiniter;                               }                               else                               {                                   totalMiniter += 0;                               }                                                     }                                               }                    }                                              }                             return totalMiniter; 


到此,我们与大家分享了启明星请假系统里,工作日的算法。如果您有好的算法,欢迎与我们联系。