编辑:
如何计算两个日期之间的总时数(包括上午8点以后的星期一的小时,但不包括下午5点以后的星期五的小时)?并排除假期和周末(我已经对此有逻辑)。
我们要在星期一上午8点至星期五下午5点之后开始计时。
示例:
// startDate = "May 19 2019 10PM" as DateTime // Sunday
// endDate = "May 21 2019 8AM" as DateTime // Tuesday
// Expected Output: 24 hr (Excludes all time before 8am on Monday)
-------------------------------------------------------
// startDate = "May 15 2019 5PM" as DateTime // Wednesday
// endDate = "May 18 2019 10AM" as DateTime // Saturday
// Expected Output: 48 hr (Excludes all time after 5PM on Friday)
public static double GetTotalHoursBetweenDays(DateTime startDate, DateTime endDate)
{
}
答案 0 :(得分:0)
使用我几年前写的BusinessDayCalculator,以下代码将使您获得DateTime对象之间的工作时间数。
void Main()
{
// Setup the BusinessDayCalculator with the relevant holidays
var bdCalc = new BusinessDayCalculator(
new List<BusinessDayCalculator.Holiday> {
BusinessDayCalculator.Holiday.NewYearsDay,
BusinessDayCalculator.Holiday.MartinLutherKingDay,
BusinessDayCalculator.Holiday.PresidentsDay,
BusinessDayCalculator.Holiday.MemorialDay,
BusinessDayCalculator.Holiday.IndependenceDay,
BusinessDayCalculator.Holiday.LaborDay,
BusinessDayCalculator.Holiday.VeteransDay,
BusinessDayCalculator.Holiday.Thanksgiving,
BusinessDayCalculator.Holiday.Christmas},
false);
// Your start and end days (spanning Memorial Day in 2010)
var fromDate = new DateTime(2019, 5, 23, 17, 0, 0);
var tillDate = new DateTime(2019, 5, 29, 13, 0 , 0);
// Total business days (including the start and end dates)
var businessDays = bdCalc.GetBusinessDaysBetweenDates(fromDate, tillDate);
// Define your working hours
var startOfBusinessHour = 8;
var endOfBusinessHour = 17;
// Calculate working hours on the first day
var startHours = fromDate.Hour >= endOfBusinessHour ? 0 : fromDate.Hour - startOfBusinessHour;
// Calculate working hours on the last day
var endHours = tillDate.Hour >= endOfBusinessHour ? 0 : tillDate.Hour - startOfBusinessHour;
// Calculate the total number of hours by
var hours = (businessDays > 2 ? (businessDays - 2) * (endOfBusinessHour - startOfBusinessHour) : 0) + startHours + endHours;
Console.WriteLine($"There are {hours} working hours between {fromDate:g} and {tillDate:g}.");
}
public static DateTime SetTime(DateTime date, Int32 hour)
{
return new DateTime(date.Year, date.Month, date.Day, hour, 0, 0);
}
public class BusinessDayCalculator
{
public enum Holiday { NewYearsEve, NewYearsDay, MartinLutherKingDay, PresidentsDay, Easter, MemorialDay, FlagDay, IndependenceDay, LaborDay, ColumbusDay, VeteransDay, Thanksgiving, DayAfterThanksgiving, Christmas };
public List<Holiday> ObservedHolidays { get; private set; }
public Boolean WeekendIncludesSaturday { get; private set; }
public BusinessDayCalculator(List<Holiday> observedHolidays, bool weekendIncludesSaturday)
{
ObservedHolidays = observedHolidays;
WeekendIncludesSaturday = weekendIncludesSaturday;
}
public DateTime AdjustForBusinessDay(DateTime date)
{
DateTime businessDay = new DateTime(date.Year, date.Month, date.Day);
while (!IsBusinessDay(businessDay))
{
businessDay = businessDay.AddDays(1);
}
return businessDay;
}
public DateTime AddBusinessDays(DateTime startDate, Int32 businessDays)
{
DateTime endDate = startDate;
int count = 0;
while (Math.Abs(businessDays) > count)
{
endDate = endDate.AddDays(businessDays > 0 ? 1 : -1);
if (IsBusinessDay(endDate))
{
count++;
}
}
return endDate;
}
public Boolean IsBusinessDay(DateTime date)
{
return !IsWeekendDay(date) && !IsHoliday(date);
}
public Boolean IsWeekendDay(DateTime date)
{
return (WeekendIncludesSaturday && date.DayOfWeek == DayOfWeek.Saturday) || date.DayOfWeek == DayOfWeek.Sunday;
}
public Boolean IsHoliday(DateTime date)
{
return ObservedHolidays.Any(holiday => GetHoliday(holiday, date).DayOfYear == date.DayOfYear);
}
public DateTime GetHoliday(Holiday holiday, DateTime date)
{
switch (holiday)
{
case Holiday.NewYearsEve:
// New year's eve always falls on the 31st of December
return AdjustHolidayForWeekend(new DateTime(date.Year, 12, 31));
case Holiday.NewYearsDay:
// New year's day always falls on the 1st of January.
return AdjustHolidayForWeekend(new DateTime(date.Year, 1, 1));
case Holiday.MartinLutherKingDay:
// Martin Luther King day is always observed on the 3rd Monday of January.
return GetNthDayOfWeekOfMonth(date.Year, 1, 3, DayOfWeek.Monday);
case Holiday.PresidentsDay:
// Presidents day or Washingtons birthday is always observed on the 3rd Monday in February.
return GetNthDayOfWeekOfMonth(date.Year, 2, 3, DayOfWeek.Monday);
case Holiday.Easter:
// We don't adjust this holiday since it's always observed on Sunday Source: http://www.smart.net/~mmontes/nature1876.html
var a = date.Year % 19;
var b = date.Year / 100;
var c = date.Year % 100;
var d = b / 4;
var e = b % 4;
var f = (b + 8) / 25;
var g = (b - f + 1) / 3;
var h = (19 * a + b - d - g + 15) % 30;
var i = c / 4;
var k = c % 4;
var l = (32 + 2 * e + 2 * i - h - k) % 7;
var m = (a + 11 * h + 22 * l) / 451;
var p = (h + l - 7 * m + 114) % 31;
var easterMonth = (h + l - 7 * m + 114) / 31;
var easterDate = p + 1;
return new DateTime(date.Year, easterMonth, easterDate);
case Holiday.MemorialDay:
// Memorial day is always on the last Monday in May
return GetLastDayOfWeekOfMonth(date.Year, 5, DayOfWeek.Monday);
case Holiday.FlagDay:
// Flag day is always on the same day June 14th
return AdjustHolidayForWeekend(new DateTime(date.Year, 6, 14));
case Holiday.IndependenceDay:
// Independence day or 4th of July is always on the same day July 4th
return AdjustHolidayForWeekend(new DateTime(date.Year, 7, 4));
case Holiday.LaborDay:
// Labor day is always on the 1st Monday in September
return GetNthDayOfWeekOfMonth(date.Year, 9, 1, DayOfWeek.Monday);
case Holiday.ColumbusDay:
// Columbus day is always on the 2nd Monday of October
return GetNthDayOfWeekOfMonth(date.Year, 10, 2, DayOfWeek.Monday);
case Holiday.VeteransDay:
// Veterans day is always on the same day November 11th
return AdjustHolidayForWeekend(new DateTime(date.Year, 11, 11));
case Holiday.Thanksgiving:
// Thanksgiving is always on the 3rd Thurday in November
return GetNthDayOfWeekOfMonth(date.Year, 11, 4, DayOfWeek.Thursday);
case Holiday.DayAfterThanksgiving:
// Day After Thanksgiving is always on the 3rd Friday in November (Black Friday)
return GetHoliday(Holiday.Thanksgiving, date).AddDays(1);
case Holiday.Christmas:
// Christmas is always on the same day December 25th
return AdjustHolidayForWeekend(new DateTime(date.Year, 12, 25));
default:
throw new ArgumentException("Unknown Holiday");
}
}
protected DateTime GetNthDayOfWeekOfMonth(Int32 year, Int32 month, Int32 week, DayOfWeek dayOfWeek)
{
DateTime date = new DateTime(year, month, 1);
while (date.DayOfWeek != dayOfWeek)
{
date = date.AddDays(1);
}
if (week > 1)
{
return date.AddDays(7 * (week - 1));
}
return date;
}
protected DateTime GetLastDayOfWeekOfMonth(Int32 year, Int32 month, DayOfWeek dayOfWeek)
{
DateTime date = new DateTime(year, month, DateTime.DaysInMonth(year, month));
while (date.DayOfWeek != dayOfWeek)
{
date = date.AddDays(-1);
}
return date;
}
protected DateTime AdjustHolidayForWeekend(DateTime holiday)
{
// Falls on Saturday, observed on Friday
if (WeekendIncludesSaturday && holiday.DayOfWeek == DayOfWeek.Saturday)
{
return holiday.AddDays(-1);
}
// Falls on Sunday, observed on Monday
if (holiday.DayOfWeek == DayOfWeek.Sunday)
{
return holiday.AddDays(1);
}
return holiday;
}
public Int32 GetBusinessDaysBetweenDates(DateTime startDate, DateTime endDate)
{
DateTime adjustedStartDate = startDate;
if (endDate < adjustedStartDate)
{
throw new Exception("end date before start date");
}
int count = 0;
while (adjustedStartDate < endDate)
{
adjustedStartDate = adjustedStartDate.AddDays(1);
if (IsBusinessDay(adjustedStartDate))
{
count++;
}
}
return count;
}
}