2011-04-10 125 views
0

我正在尝试计算基于每天工作指定小时数的两个日期之间的天数。我无法确定在一天内选择了多少个全天和半天,例如如果在日历上选择了1天,那么这实际上是1整天。根据工作日中的小时计算小时数

如果09:00当天选择了一个,并在第2天说出13:00,那么这将是大约12个工作小时和1.5天。

编辑:最后,希望最后的更新,这说明最终的结果代码,以使这一问题在未来

还需加银行假日检查等更具有可读性,但它大致有)

//Validate working day rules are available 
        List<DayOfWeek> lDaysValidated = new List<DayOfWeek>(); 
        double dTotalDays = 0; 

        //loop though the days between the two dates 
        for (var day = dtStartDate; day <= dtEndTime; day = day.AddDays((1))) 
        { 
         //Only perform validation if the day of week has not already been validated 
         if (!lDaysValidated.Contains(day.DayOfWeek)) 
         { 
          //Look for working day rules for the user 
          List<UserTimeRule> lWorkingDayRules = UserTimeRule.GetUserTimeRules(
           this.CurrentHolidayRequest.RequestedByID, 
           day.DayOfWeek, 
           false, 
           Settings.Instance.CostingModule, 
           TimeRuleRecordTypeEnum.DayRule); 

          //If the user has no rules, check the defaults 
          if (lWorkingDayRules.Count == 0) 
          { 
           //Get default rules for the day of week 
           lWorkingDayRules = UserTimeRule.GetDefaultUserTimeRules(
            day.DayOfWeek); 

           //If there is still no day rule, show error message and return 
           if (lWorkingDayRules.Count == 0) 
           { 
            //Show error message 
            lblWorkingDaysError.Text = 
             String.Format(
              "* The current user has no working day rules set up, and there is no default day rule for '{0}'", 
              day.DayOfWeek); 

            return; 
           } 
           else 
           { 
            //Calculate the working days 
            this.CalculateWorkingDays(
             ref dtStartDate, 
             ref dtEndTime, 
             day, 
             lWorkingDayRules, 
             ref dTotalDays 
             ); 

            //Add the day of week to the list of already validated days 
            lDaysValidated.Add(day.DayOfWeek); 
           } 
          } 
          else 
          { 
           //Calculate the working days 
           this.CalculateWorkingDays(
            ref dtStartDate, 
            ref dtEndTime, 
            day, 
            lWorkingDayRules, 
            ref dTotalDays 
            ); 

           //Add the day of week to the list of already validated days 
           lDaysValidated.Add(day.DayOfWeek); 
          } 
         } 
        } 

        #endregion Validate 

        #region Update Details 

        //Set the Dates 
        this.CurrentHolidayRequestLine.StartTime = dtStartDate; 
        this.CurrentHolidayRequestLine.EndTime = dtEndTime; 

        //Set the number of Days 
        this.CurrentHolidayRequestLine.Days = Convert.ToDecimal(dTotalDays); 

而且计算总天数的方法:

/// <summary> 
     /// Calculates the number of working days for a specified day 
     /// </summary> 
     /// <param name="dtHolidayStartTime">The start time of the holiday request</param> 
     /// <param name="dtHolidayEndTime">The end time of the holiday request</param> 
     /// <param name="dtCurrentDay">The current day being evaluated</param> 
     /// <param name="lWorkingDayRules">The current set of working day rules</param> 
     /// <param name="dTotalDays">A reference to the total days on the request</param> 
     [VersionChange("7.3.88.271", "10/04/2011", "Method added to calculate No days on a request")] 
     private void CalculateWorkingDays(ref DateTime dtHolidayStartTime, ref DateTime dtHolidayEndTime, DateTime dtCurrentDay, List<UserTimeRule> lWorkingDayRules, ref double dTotalDays) 
     { 
      try 
      { 
       //Check whether Holiday start time is before the start time of the working day 
       if (dtHolidayStartTime.TimeOfDay < lWorkingDayRules[ 0 ].StartTime.TimeOfDay) 
       { 
        dtHolidayStartTime = new DateTime(
         dtHolidayStartTime.Year, 
         dtHolidayStartTime.Month, 
         dtHolidayStartTime.Day, 
         lWorkingDayRules[ 0 ].StartTime.Hour, 
         lWorkingDayRules[ 0 ].StartTime.Minute, 
         lWorkingDayRules[ 0 ].StartTime.Minute); 
       } 
       //Check whether the holiday end time is after the end time of a nomal working day 
       if (dtHolidayEndTime.TimeOfDay > lWorkingDayRules[ 0 ].EndTime.TimeOfDay) 
       { 
        dtHolidayEndTime = new DateTime(
         dtHolidayEndTime.Year, 
         dtHolidayEndTime.Month, 
         dtHolidayEndTime.Day, 
         lWorkingDayRules[ 0 ].EndTime.Hour, 
         lWorkingDayRules[ 0 ].EndTime.Minute, 
         lWorkingDayRules[ 0 ].EndTime.Minute); 
       } 
       //Check whether the holiday end time is after lunch time, but before the end of the day 
       if (dtHolidayEndTime.TimeOfDay > lWorkingDayRules[ 0 ].LunchEndTime.TimeOfDay 
        && dtHolidayEndTime.TimeOfDay < lWorkingDayRules[ 0 ].EndTime.TimeOfDay) 
       { 
        dtHolidayEndTime = new DateTime(
         dtHolidayEndTime.Year, 
         dtHolidayEndTime.Month, 
         dtHolidayEndTime.Day, 
         lWorkingDayRules[ 0 ].LunchEndTime.Hour, 
         lWorkingDayRules[ 0 ].LunchEndTime.Minute, 
         lWorkingDayRules[ 0 ].LunchEndTime.Minute); 
       } 

       //Create a date time object for the end current working day 
       DateTime dtWorkingDayEndTime = new DateTime(
        dtCurrentDay.Year, 
        dtCurrentDay.Month, 
        dtCurrentDay.Day, 
        lWorkingDayRules[ 0 ].EndTime.Hour, 
        lWorkingDayRules[ 0 ].EndTime.Minute, 
        lWorkingDayRules[ 0 ].EndTime.Second); 

       //Create a date time object for the end of lunch 
       DateTime dtWorkingDayLunchTime = new DateTime(
        dtCurrentDay.Year, 
        dtCurrentDay.Month, 
        dtCurrentDay.Day, 
        lWorkingDayRules[ 0 ].LunchEndTime.Hour, 
        lWorkingDayRules[ 0 ].LunchEndTime.Minute, 
        lWorkingDayRules[ 0 ].LunchEndTime.Second); 

       //Create a date time object for the start of the current day 
       DateTime dtWorkingDayStartTime = new DateTime(
        dtCurrentDay.Year, 
        dtCurrentDay.Month, 
        dtCurrentDay.Day, 
        lWorkingDayRules[ 0 ].StartTime.Hour, 
        lWorkingDayRules[ 0 ].StartTime.Minute, 
        lWorkingDayRules[ 0 ].StartTime.Second); 

       //Check whether to add the first half of the day 
       if (dtHolidayEndTime >= dtWorkingDayLunchTime) 
       { 
        dTotalDays += 0.5f; 
       } 

       //Check whether to add the second half of the day 
       if (dtHolidayEndTime >= dtWorkingDayEndTime) 
       { 
        dTotalDays += 0.5f; 
       } 
      } 
      catch (Exception) 
      { 
       throw; 
      } 
     } 
+0

不要忘记考虑夏令时。 – 2011-04-10 12:59:27

+0

我已经写了一个库,可以很容易地执行这种计算。一年多以来,它已经在一家客户的全天候生产中使用了一年多,用于各种复杂的全球日历计算。如果您对许可产品感兴趣,请告诉我。 (我没有它的网站) – 2011-04-10 13:07:42

+0

@uosɐs:我不认为你正在回应他的答案或帮助他解决他的问题... – Marco 2011-04-10 14:47:39

回答

1

试试这个。这段代码不是用VS编写的,所以它可能不完美......只能使用它内部的逻辑。

int htot = 0, dtot = 0; 
while (date2>date1) { 
    int h1 = date1.Hour < work_start ? work_start : date1.Hour; 
    int h2 = date1.Hour > work_end ? work_end : date1.Hour; 
    htot += (h2-h1); 
    dtot++; 
    date1 = date1.AddDays(1); 
} 
+0

@Marco - 感谢您的回复,我尝试了一些类似于您的建议的内容,但我不认为自己已正确实施或者误解了,我已经用更新的代码部分编辑了我的问题。 – WraithNath 2011-04-10 12:46:22

+0

我选择了*日期,因为如果在两个日期之间只选择了1天(在十进制值处出现的零数小于1),那么这会导致问题。现在的问题是//将总工作日数除以指定工作日的总工时总数小时dTotalWorkingDays = dTotalHoursOnClaim/dHoursInWorkingDays;总是出现在1.0 – WraithNath 2011-04-10 12:58:36

+1

@WraitNath:我的想法是计算整数天的总数(这里是为什么天是宣布并转换为int),所以如果date2是第1天后的天,天应该是0或1,具体取决于如果hour1是大于hour2。我要检查... – Marco 2011-04-10 13:07:41