【问题标题】:Work out number of hours based on hours in working day根据工作日的小时数计算小时数
【发布时间】:2011-04-10 12:00:06
【问题描述】:

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

如果选择第一天的 09:00 并说第二天的 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;
            }
        }

【问题讨论】:

  • 别忘了考虑夏令时。
  • 我写了一个库,可以很容易地执行这种计算。一年多来,它已在一个客户 24/7 的生产环境中用于各种复杂的全球日历计算。如果您对许可产品感兴趣,请告诉我。 (我没有网站)
  • @uosɐſ:我不认为你在回应他的回答或帮助他解决问题......
  • @Marco - 如果他可以考虑打包解决方案。人们在适当的地方提供 jQuery、Telerik 等。他可能不感兴趣,但这就是我没有将其发布为答案的原因。
  • 用多种方法分解您的代码,使其更具可读性。

标签: c# .net datetime


【解决方案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);
}

【讨论】:

  • @WraitNath:我的想法是计算整数天的总数(这就是为什么声明天并将其转换为 int 的原因)所以如果 date2 是 day1 的后一天,则天应该是 0 或 1,具体取决于小时 1 大于小时 2。我要检查...
  • @WraitNath:好的,再试一次。我现在不能写代码,但试试这个。对于 date1 和 date2 之间的每一天,您必须检查以下内容:如果 start_hour 小于 work_starting_hour 则 start_hour=work_starting_hour;如果 end_hour 大于 work_end_hour,则 end_hour=work_end_hour。因此,对于每一天,您都可以合计 total_hours 并增加 total_days。我在不使用 VS 的情况下尝试使用代码,因此请原谅一些错误并仅使用“逻辑”。
  • @WraitNath:请注意,我的代码只使用了几个小时,但也许你也应该检查分钟......
  • @WraithNath:我发布和编辑的代码不适合你?
  • @WraithNath:请记住,正如我在之前的评论中告诉你的那样,我只工作了几个小时,但按照逻辑并在几分钟内使用它......
猜你喜欢
  • 1970-01-01
  • 2022-07-22
  • 2014-05-22
  • 2020-11-02
  • 1970-01-01
  • 1970-01-01
  • 2016-04-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多