zoukankan      html  css  js  c++  java
  • 启明星请假系统里,计算工作日的实现

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

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


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

  • 相关阅读:
    SQL SERVER 2008 获取当前月,当前月前一月,当前月后一月
    SQL SERVER 2008 获取当前月,当前月前一月,当前月后一月
    SQL重复记录查询的一些方法
    TSQL日期处理总结
    50种方法巧妙优化SQL Server数据库
    DAMMIF
    CRYSOL
    Damaver
    DAMMIN
    AutoMerge
  • 原文地址:https://www.cnblogs.com/mqingqing123/p/3807493.html
Copyright © 2011-2022 走看看