所以,我正在尝试计算符合某些标准的两个日期之间的时间(这里:工作/非工作),我对结果感到困惑,因为我无法找出错误原因。
但首先是一些代码;
**Input Date A:** 2009-01-01 2:00 pm
**Input Date B:** 2009-01-02 9:00 am
因此,正如您所看到的,总时间跨度(例如按DateB.Substract(DateA)
计算) 19 小时。
我现在想要计算这个时间段内“非工作”小时的小时数,基于上午8点到下午5点的平均工作日 - 结果应该 15小时(所以,19 - 15 =总工作时间为4小时)(下午2:00至下午5:00加上午8:00至上午9:00)
但是,遵循我的代码
DateTime _Temp = new DateTime(2009, 1, 1, 14, 0, 0);
DateTime _End = new DateTime(2009, 1, 2, 9, 0, 0);
int _WorkDayStart = 8;
int _WorkDayEnd = 17;
int _Return = 0;
while (_End > _Temp)
{
if (_Temp.Hour <= _WorkDayStart || _Temp.Hour >= _WorkDayEnd)
_Return++;
_Temp = _Temp.AddHours(1);
}
结果是 16小时(19 - 16 = 3小时的总工作时间) - 我没有看到错误在哪里,所以有一个小时失踪?!我在纸上重构它,它应该按预期工作......但不是: - /
有人看到了这个错误吗?
答案 0 :(得分:3)
你计算两个结束为非工作,而不只是一个。这一行:
if (_Temp.Hour <= _WorkDayStart || _Temp.Hour >= _WorkDayEnd)
应该是:
if (_Temp.Hour < _WorkDayStart || _Temp.Hour >= _WorkDayEnd)
你有效地走过了“开始时间”。因此,8am本身应该算作工作时间,因为它是工作时间的 start ,但是下午5点不会,因为它是非工作时间的 start 。 / p>
我也强烈建议您在if
语句的主体周围放置大括号,或者至少缩进以下行。 (我进一步建议你使用camelCase
作为局部变量,但这只是一个惯例 - 我以前从未见过使用该约定为局部变量编写的C#代码。你可能想要阅读{{3 - 它没有指定局部变量,但它们;通常在驼峰的情况下。)
最后,我个人觉得更容易阅读左边的“正在改变的事情” - 所以我将你的循环条件改为:
while (_Temp < _End)
另一种方法是将其更改为for循环。通过所有这些更改,代码将是:
DateTime start = new DateTime(2009, 1, 1, 14, 0, 0);
DateTime end = new DateTime(2009, 1, 2, 9, 0, 0);
int workDayStart = 8;
int workDayEnd = 17;
int nonWorkHours = 0;
for (DateTime time = start; time < end; time = time.AddHours(1))
{
if (time.Hour < workDayStart || time.Hour >= workDayEnd)
{
nonWorkHours++;
}
}
最后,将其提取到一个方法中:
public static int CountNonWorkHours(DateTime start, DateTime end,
int workDayStart, int workDayEnd)
{
int nonWorkHours = 0;
for (DateTime time = start; time < end; time = time.AddHours(1))
{
if (time.Hour < workDayStart || time.Hour >= workDayEnd)
{
nonWorkHours++;
}
}
return nonWorkHours;
}
编辑:关于konamiman的建议......是的,每小时循环是非常低效的。但是,要做到这一点相对容易。除非你打算长时间使用 lot ,否则我会使用这个相当简单的代码。如果您尝试执行每日版本,那么在各种情况下最终会出现逐个错误。虽然我不喜欢效率低下的代码,但如果它没有伤害我,我不介意它:)
答案 1 :(得分:1)
如果您打算重用此代码,我会重构它以避免循环。您可以将整天的数量乘以每天的工时,然后将间隔的第一天和最后一天视为特殊情况。
答案 2 :(得分:0)
您也可以使用它来避免循环
DateTime startDate = new DateTime(2009, 1, 1, 14, 0, 0);
DateTime endDate = new DateTime(2009, 1, 2, 9, 0, 0);
int startTime = 8;
int endTime = 17;
int ret = ((endDate.Subtract(startDate).Days - 1) * 8)
+ (startDate.Hour >= startTime && startDate.Hour < endTime ? endTime - startDate.Hour : 0)
+ (endDate.Hour > startTime && endDate.Hour <= endTime ? endDate.Hour - startTime : 0);