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

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

在请假前,我们假定,公司的工作时间是 上午: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; 


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

 

posted @ 2014-06-25 10:13  启明星工作室  阅读(860)  评论(0编辑  收藏  举报