2011-04-10 75 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