【发布时间】:2015-02-10 20:36:32
【问题描述】:
我正在寻找一些优雅的算法来计算多天的小时数,并使用预定义的“work-hour-day-range”。
一个真实的例子是:只计算一个租用对象的工作时间。
DataTime 范围可以在定义的“work-hour-day-range”之内或之外开始。
示例
我创建了一个包含 5 种不同场景的小示例。希望这能让它更清楚。
- 第 1 行 = 日期
- 第 2 行 = 白天-时间-小时
- 第 3-7 行 = 5 个不同的日期范围来计算小时数
我想到的唯一方法是在范围内的每一天和多个复杂的 if-the 树内进行 for 循环。但我希望有人比我更聪明,可以给我一点提示,让我找到一些更快更优雅的方式。
非常感谢您的帮助! :)
更新 1
基于 Lashanes answere,我以这种方式实现了它...
public struct DateSpan
{
public DateTime begin, end;
public DateSpan(DateTime begin, DateTime end)
{
if (begin > end || end < begin)
throw new Exception("Not possible");
this.begin = begin;
this.end = end;
}
public DateTime Begin
{
get
{
return this.begin;
}
}
public DateTime End
{
get
{
return this.end;
}
}
public TimeSpan TimeSpan
{
get
{
return this.End - this.Begin;
}
}
public TimeSpan GetWorkTimeSpan(TimeSpan? workTimeBegin, TimeSpan? workTimeEnd)
{
if (this.Begin.Date == this.End.Date)
{
long totalWorkTimeTicks = Math.Min(workTimeEnd.Value.Ticks, this.End.Ticks) - Math.Max(workTimeBegin.Value.Ticks, this.Begin.Ticks);
return TimeSpan.FromTicks(totalWorkTimeTicks);
}
else
{
TimeSpan dailyWorkTime = TimeSpan.FromDays(1);
dailyWorkTime -= workTimeBegin ?? TimeSpan.Zero;
dailyWorkTime -= TimeSpan.FromDays(1) - workTimeEnd ?? TimeSpan.FromDays(1);
long totalDaysWorkTimeTicks = (int)(this.TimeSpan.TotalDays) * dailyWorkTime.Ticks;
long firstDayWorkTimeTicks = Math.Min(dailyWorkTime.Ticks, Math.Max(0, workTimeEnd.Value.Ticks - this.Begin.TimeOfDay.Ticks));
long lastDayWorkTimeTicks = Math.Min(dailyWorkTime.Ticks, Math.Max(0, this.End.TimeOfDay.Ticks - workTimeBegin.Value.Ticks));
return TimeSpan.FromTicks(firstDayWorkTimeTicks + totalDaysWorkTimeTicks + lastDayWorkTimeTicks);
}
}
}
还有测试用例...
DateSpan dateRange1 = new DateSpan(new DateTime(2012, 01, 01, 07, 00, 00), new DateTime(2012, 01, 03, 15, 00, 00));
DateSpan dateRange2 = new DateSpan(new DateTime(2012, 01, 01, 02, 00, 00), new DateTime(2012, 01, 03, 20, 00, 00));
DateSpan dateRange3 = new DateSpan(new DateTime(2012, 01, 01, 04, 00, 00), new DateTime(2012, 01, 03, 23, 00, 00));
DateSpan dateRange4 = new DateSpan(new DateTime(2012, 01, 01, 23, 00, 00), new DateTime(2012, 01, 03, 09, 00, 00));
DateSpan dateRange5 = new DateSpan(new DateTime(2012, 01, 02, 12, 00, 00), new DateTime(2012, 01, 02, 20, 00, 00));
Debug.WriteLine(String.Format("dateRange1: {0}", dateRange1.GetWorkTimeSpan(new TimeSpan(04, 00, 00), new TimeSpan(17, 00 ,00)).TotalHours));
Debug.WriteLine(String.Format("dateRange2: {0}", dateRange2.GetWorkTimeSpan(new TimeSpan(04, 00, 00), new TimeSpan(17, 00, 00)).TotalHours));
Debug.WriteLine(String.Format("dateRange3: {0}", dateRange3.GetWorkTimeSpan(new TimeSpan(04, 00, 00), new TimeSpan(17, 00, 00)).TotalHours));
Debug.WriteLine(String.Format("dateRange4: {0}", dateRange4.GetWorkTimeSpan(new TimeSpan(04, 00, 00), new TimeSpan(17, 00, 00)).TotalHours));
Debug.WriteLine(String.Format("dateRange5: {0}", dateRange5.GetWorkTimeSpan(new TimeSpan(04, 00, 00), new TimeSpan(17, 00, 00)).TotalHours));
结果是..
dateRange1: 47 // should be 37h
dateRange2: 52 // should be 42h
dateRange3: 52 // should be 42h
dateRange4: 18 // should be 20h
dateRange5: -17628067 // should be 6h
我做错了什么?我想我理解 Lashane 解释的方式,但没有看到我的错误...... :(
【问题讨论】:
-
这个问题对我来说不是很清楚。您能否提供使用具体数据的简单示例(最好是可编译的)?
-
我试图使示例更精确,但我无法提供一些代码,因为这是我试图寻求帮助的原因。 ^^