【发布时间】: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 等。他可能不感兴趣,但这就是我没有将其发布为答案的原因。
-
用多种方法分解您的代码,使其更具可读性。