Определите разницу между двумя DateTimes, только считая часы работы
Для нашего программного обеспечения поддержки на С# мне нужно определить временной интервал между двумя DateTimes, но мне нужно только подсчитать часы работы (например, с будних дней с 09:00 до 17:00).
Итак, например, если первое DateTime - 15/02/2011 16:00, а второе - 16/02/2011 10:00, метод должен вернуть 2 часа.
Любая помощь очень ценится!
Ответы
Ответ 1
DateTime start = DateTime.Parse("15/02/2011 16:00");
DateTime end = DateTime.Parse("16/02/2011 10:00");
int count = 0;
for (var i = start; i < end; i = i.AddHours(1))
{
if (i.DayOfWeek != DayOfWeek.Saturday && i.DayOfWeek != DayOfWeek.Sunday)
{
if (i.TimeOfDay.Hours >= 9 && i.TimeOfDay.Hours < 17)
{
count++;
}
}
}
Console.WriteLine(count);
Ответ 2
Здесь мы идем, потратили некоторое время на это для вас.:)
Имеет место для обнаружения праздников (если вы пишете функцию, которая проверяет, является ли DateTime
праздником), определяет выходные дни между датами и обрабатывает больше, чем часы.
Алгоритм состоит в том, чтобы вычислить, сколько времени с начала до конца бизнеса и от начала бизнеса до конечного времени, а затем вычислить, сколько дней находится между ними. Падение на ту же дату - особый случай.
Предостережение: я провел некоторое базовое тестирование, но, вероятно, не получил все угловые случаи.
public static TimeSpan BusinessTimeDelta(DateTime start, DateTime stop)
{
if (start == stop)
return TimeSpan.Zero;
if (start > stop)
{
DateTime temp = start;
start = stop;
stop = temp;
}
// First we are going to truncate these DateTimes so that they are within the business day.
// How much time from the beginning til the end of the day?
DateTime startFloor = StartOfBusiness(start);
DateTime startCeil = CloseOfBusiness(start);
if (start < startFloor) start = startFloor;
if (start > startCeil) start = startCeil;
TimeSpan firstDayTime = startCeil - start;
bool workday = true; // Saves doublechecking later
if (!IsWorkday(start))
{
workday = false;
firstDayTime = TimeSpan.Zero;
}
// How much time from the start of the last day til the end?
DateTime stopFloor = StartOfBusiness(stop);
DateTime stopCeil = CloseOfBusiness(stop);
if (stop < stopFloor) stop = stopFloor;
if (stop > stopCeil) stop = stopCeil;
TimeSpan lastDayTime = stop - stopFloor;
if (!IsWorkday(stop))
lastDayTime = TimeSpan.Zero;
// At this point all dates are snipped to within business hours.
if (start.Date == stop.Date)
{
if (!workday) // Precomputed value from earlier
return TimeSpan.Zero;
return stop - start;
}
// At this point we know they occur on different dates, so we can use
// the offset from SOB and COB.
TimeSpan timeInBetween = TimeSpan.Zero;
TimeSpan hoursInAWorkday = (startCeil - startFloor);
// I tried cool math stuff instead of a for-loop, but that leaves no clean way to count holidays.
for (DateTime itr = startFloor.AddDays(1); itr < stopFloor; itr = itr.AddDays(1))
{
if (!IsWorkday(itr))
continue;
// Otherwise, it a workday!
timeInBetween += hoursInAWorkday;
}
return firstDayTime + lastDayTime + timeInBetween;
}
public static bool IsWorkday(DateTime date)
{
// Weekend
if (date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday)
return false;
// Could add holiday logic here.
return true;
}
public static DateTime StartOfBusiness(DateTime date)
{
return new DateTime(date.Year, date.Month, date.Day, 9, 0, 0);
}
public static DateTime CloseOfBusiness(DateTime date)
{
return new DateTime(date.Year, date.Month, date.Day, 17, 0, 0);
}
Ответ 3
Используйте LINQ:
DateTime dt1 = new DateTime(2010, 10, 1, 16, 0, 0);
DateTime dt2 = new DateTime(2010, 10, 2, 10, 0, 0);
int hours = Enumerable.Range(1, (dt2 - dt1).Hours)
.Where(h =>
{
var dt = dt1.AddHours(h);
return dt.DayOfWeek != DayOfWeek.Saturday
&& dt.DayOfWeek != DayOfWeek.Sunday
&& dt.Hour >= 9 && dt.Hour <= 17;
}).Count();
Здесь я предполагаю, что все Minute
и Second
равны нулю. В противном случае (dt2 - dt1).Hours
даст неожиданное значение.
Ответ 4
Попробуйте посмотреть здесь аналогичный вопрос: Расчет прошедшего рабочего времени между 2 днями времени
Ответ 5
Вы можете попробовать этот алгоритм:
- Рассчитать общее количество часов (скажем, TotalHours = (Date2 - Date1).TotalHours)
- Рассчитайте количество праздников (праздники, включая выходные и другие праздники).
- Calcualte No of Working days ((Date2-Date1).TotalDays - Holidays) as int
Рабочие часы = TotalHours - 24 * праздники - 16 * WorkDays
(16 = Разница во времени между 17:00 и 9:00 следующего дня)
Ответ 6
попробуйте это
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var date1 = new DateTime(2010, 10, 12, 12, 00, 00);
var date2 = new DateTime(2010, 10, 14, 15, 00, 00);
var hr1 = ((date1.Hour > 9) && (date1.Hour < 17)) ? 17 - date1.Hour : 0;
var hr2 = ((date2.Hour > 9) && (date2.Hour < 17)) ? 17 - date2.Hour : 0;
var middleHours = ((date2.Date - date1.Date).Days -1) * 8 ;
Console.WriteLine(hr1+hr2+ middleHours);
Console.ReadKey();
}
}
}
Я попробовал, и он работает:)