C# 计算2个datetime之间经过的工作时间
两次约会。计算他们之间工作时间的最佳方法是什么。考虑到工作时间是周一8-5.30,周二-周五8.30-5.30,并且任何一天都可能是公共假日 这是我的努力,看起来效率非常低,但就迭代次数而言,IsWorkingDay方法点击DB查看datetime是否为公共假日 有人能提出任何优化或替代方案吗C# 计算2个datetime之间经过的工作时间,c#,datetime,date,C#,Datetime,Date,两次约会。计算他们之间工作时间的最佳方法是什么。考虑到工作时间是周一8-5.30,周二-周五8.30-5.30,并且任何一天都可能是公共假日 这是我的努力,看起来效率非常低,但就迭代次数而言,IsWorkingDay方法点击DB查看datetime是否为公共假日 有人能提出任何优化或替代方案吗 public decimal ElapsedWorkingHours(DateTime start, DateTime finish) { decimal co
public decimal ElapsedWorkingHours(DateTime start, DateTime finish)
{
decimal counter = 0;
while (start.CompareTo(finish) <= 0)
{
if (IsWorkingDay(start) && IsOfficeHours(start))
{
start = start.AddMinutes(1);
counter++;
}
else
{
start = start.AddMinutes(1);
}
}
decimal hours;
if (counter != 0)
{
hours = counter/60;
}
return hours;
}
公共十进制ElapsedWorkingHours(日期时间开始,日期时间结束)
{
十进制计数器=0;
while(开始。比较到(完成)
特别是考虑到IsWorkingDay方法会点击DB以查看该天是否为公共假日
如果问题是查询的数量而不是数据量,则在开始时从数据库中查询所需的整个工作日范围的工作日数据,而不是在每个循环迭代中查询。在开始优化之前,问自己两个问题
a) 它有用吗
b) 是不是太慢了
只有当两个问题的答案都是“是”时,您才准备好开始优化
除此之外
- 你只需要担心开始日和结束日的分钟数和小时数。中间的日子显然是整整9/9.5小时,除非是节假日或周末
- 不需要查看周末是否是假日
我会这样做的
// Normalise start and end
while start.day is weekend or holiday, start.day++, start.time = 0.00am
if start.day is monday,
start.time = max(start.time, 8am)
else
start.time = max(start.time, 8.30am)
while end.day is weekend or holiday, end.day--, end.time = 11.59pm
end.time = min(end.time, 5.30pm)
// Now we've normalised, is there any time left?
if start > end
return 0
// Calculate time in first day
timediff = 5.30pm - start.time
day = start.day + 1
// Add time on all intervening days
while(day < end.day)
// returns 9 or 9.30hrs or 0 as appropriate, could be optimised to grab all records
// from the database in 1 or 2 hits, by counting all intervening mondays, and all
// intervening tue-fris (non-holidays)
timediff += duration(day)
// Add time on last day
timediff += end.time - 08.30am
if end.day is Monday then
timediff += end.time - 08.00am
else
timediff += end.time - 08.30am
return timediff
//正常化开始和结束
当start.day是周末或假日时,start.day++,start.time=0.00am
如果开始日是星期一,
start.time=最大值(start.time,上午8点)
其他的
start.time=最大值(start.time,上午8:30)
当end.day为周末或假日时,end.day--,end.time=11.59pm
结束时间=分钟(结束时间,下午5:30)
//现在我们已经恢复正常了,还有时间吗?
如果开始>结束
返回0
//计算第一天的时间
timediff=5.30pm-start.time
天=开始。天+1
//在所有中间日期添加时间
而(日<结束日)
//返回9或9.30小时或0(视情况而定),可以优化以获取所有记录
//从数据库中点击1或2次,通过计算所有中间的星期一和所有
//星期二至五(非节假日)
timediff+=持续时间(天)
//添加最后一天的时间
timediff+=结束时间-上午8时30分
如果今天是星期一,那么
timediff+=结束时间-上午8时
其他的
timediff+=结束时间-上午8时30分
返回时间差
你可以这样做
从假日中选择计数(天),其中假日按天在@Start和@End组之间
计算星期一、星期二、星期三等的假期数。这可能是一种让SQL只计算星期一和非星期一的方法,但目前还想不出任何东西。看看TimeSpan类。这将为您提供任意两次之间的小时数
一次DB呼叫也可以在您的两次通话之间获得假期;大致如下:
SELECT COUNT(*) FROM HOLIDAY WHERE HOLIDAY BETWEEN @Start AND @End
把这个数字乘以8,然后从你的总小时数中减去它
-伊恩
编辑:作为对以下内容的回应,如果你是假日,那么你的假期不是固定的小时数。你可以在数据库中保留一个假日开始
和一个假日结束
时间,并且只需从数据库调用中返回它们。做一个小时计数,类似于你为主例程确定的任何方法。@OregonGhost所说的,不是在接受一天并返回布尔值时使用IsWorkingDay()函数,而是使用HolidayCount()函数函数,该函数接受一个范围并返回一个整数,给出该范围内的假期数。这里的诀窍是,如果您处理的是边界开始日和结束日的部分日期,您可能仍然需要确定这些日期本身是否为假期。但即使如此,您也可以使用新方法确保最多需要三天调用数据库。尝试以下方法:
TimeSpan = TimeSpan Between Date1 And Date2
cntDays = TimeSpan.Days
cntNumberMondays = Iterate Between Date1 And Date2 Counting Mondays
cntdays = cntdays - cntnumbermondays
NumHolidays = DBCall To Get # Holidays BETWEEN Date1 AND Date2
Cntdays = cntdays - numholidays
numberhours = ((decimal)cntdays * NumberHoursInWorkingDay )+((decimal)cntNumberMondays * NumberHoursInMondayWorkDay )
还有递归解决方案。不一定高效,但很有趣:
public decimal ElapseddWorkingHours(DateTime start, DateTime finish)
{
if (start.Date == finish.Date)
return (finish - start).TotalHours;
if (IsWorkingDay(start.Date))
return ElapsedWorkingHours(start, new DateTime(start.Year, start.Month, start.Day, 17, 30, 0))
+ ElapsedWorkingHours(start.Date.AddDays(1).AddHours(DateStartTime(start.Date.AddDays(1)), finish);
else
return ElapsedWorkingHours(start.Date.AddDays(1), finish);
}
<> P>最有效的方法是计算总时差,然后减去周末或假日的时间。有很多边缘情况需要考虑,但是你可以通过计算范围的第一天和最后几天来简化计算。
所建议的COUNT(*)方法似乎是计算假期的一个好方法。无论您使用什么方法,它都只处理整天,您需要分别涵盖开始日期和结束日期
计算周末是很容易的;如果您有一个函数Weekday(date),它返回0表示星期一,返回6表示星期天,则它如下所示:
saturdays = ((finish - start) + Weekday(start) + 2) / 7;
sundays = ((finish - start) + Weekday(start) + 1) / 7;
注意:(finish-start)不是字面意义上的,用计算时间跨度(以天为单位)来代替它。使用@Ian的查询来检查日期之间的差异,找出哪些天不是工作日。然后做一些数学运算,找出你的开始时间或结束时间是否在非工作日,并减去差值
因此,如果开始时间是星期六中午,结束时间是星期一中午,则查询应返回2天,从中计算48小时(2 x 24)。如果您在IsWorkingDay(开始)上的查询返回false,则从24减去从开始到午夜的时间,这将给您12小时,或36小时的总非工作时间
现在,如果你每天的办公时间都一样,你就会做类似的事情。如果你的办公时间有点分散,你就会有更多的麻烦
理想情况下,对数据库进行一次查询,查询出两次(甚至两次日期)之间的所有办公时间。然后从该集合中进行本地计算。Dim totalMinutes As Integer=0
Dim totalMinutes As Integer = 0
For minute As Integer = 0 To DateDiff(DateInterval.Minute, contextInParameter1, contextInParameter2)
Dim d As Date = contextInParameter1.AddMinutes(minute)
If d.DayOfWeek <= DayOfWeek.Friday AndAlso _
d.DayOfWeek >= DayOfWeek.Monday AndAlso _
d.Hour >= 8 AndAlso _
d.Hour <= 17 Then
totalMinutes += 1
Else
Dim test = ""
End If
Next minute
Dim totalHours = totalMinutes / 60
对于分钟作为整数=0到DateDiff(DateInterval.minute、contextInParameter1、contextInParameter2)
Dim d As Date=contextInParameter1.AddMinutes(分钟)
如果d.DayOfWeek=DayOfWeek.Monday和Also_
d、 小时>=8安达索_
d、 多少小时