一個日期段如工作時間為 8:00 至 17:00
public class TimeHelper
{
/// <summary>
/// 計算時間間隔
/// </summary>
/// <param name="tsStart"></param>
/// <param name="tsEnd"></param>
/// <param name="time_start"></param>
/// <param name="time_end"></param>
/// <returns></returns>
public static TimeSpan GetTimeSpan(TimeSpan tsStart, TimeSpan tsEnd, TimeSpan time_start, TimeSpan time_end)
{
if (tsStart > tsEnd)
return new TimeSpan(0);
if (tsEnd < time_start)
return new TimeSpan(0);
if (tsStart > time_end)
return new TimeSpan(0);
if (tsStart >= time_start && tsStart <= time_end)
time_start = tsStart;
if (tsEnd <= time_end && tsEnd >= time_start)
time_end = tsEnd;
return time_end - time_start;
}
/// <summary>
/// 獲取兩日期的工作時間間隔
/// </summary>
/// <param name="dtStart"></param>
/// <param name="dtEnd"></param>
/// <param name="time_start"></param>
/// <param name="time_end"></param>
/// <returns></returns>
public static TimeSpan GetDateTimeSpan(DateTime dtStart, DateTime dtEnd, TimeSpan time_start, TimeSpan time_end)
{
if (dtStart.Date == dtEnd.Date) //如果是同一天
{
if (IsWorkDay(dtStart))
return GetTimeSpan(dtStart.TimeOfDay, dtEnd.TimeOfDay, time_start, time_end);
else
return new TimeSpan(0);
}
//如果不是同一天 計算天數減去1 乘以標准時長 加上分別計算開始開數和結束天數
double days = dtEnd.Date.Subtract(dtStart.Date).TotalDays - 1;
TimeSpan startTimeSpan;
if (IsWorkDay(dtStart))
startTimeSpan = GetTimeSpan(dtStart.TimeOfDay, new TimeSpan(23, 59, 60), time_start, time_end);//開始天
else
startTimeSpan = new TimeSpan(0);
TimeSpan endTimeSpan;
if (IsWorkDay(dtEnd))
endTimeSpan = GetTimeSpan(new TimeSpan(0, 0, 0), dtEnd.TimeOfDay, time_start, time_end);//結束天
else
endTimeSpan = new TimeSpan(0);
TimeSpan totalTimeSpan = startTimeSpan + endTimeSpan; //總值
TimeSpan preTimeSpan = time_end - time_start;
for (int i = 1; i <=days; i++)
{
if (IsWorkDay(dtStart.AddDays(i)))
totalTimeSpan += preTimeSpan; //添加間隔天
}
return totalTimeSpan;
}
/// <summary>
/// 判斷是否為工作日
/// </summary>
/// <param name="dt"></param>
/// <returns></returns>
public static bool IsWorkDay(DateTime dt)
{
//先從日期表中,查找不是上班時間,如果不是直接返回 false ,如果是,直接返回 true。
//如果在日期表中,找不到,則查找定義的日歷,依據日歷定義的周末時間來定義是否為工作日。
//獲取日歷中不上班的標准周末時間,判斷是不是上班時間
if (dt.DayOfWeek == DayOfWeek.Sunday || dt.DayOfWeek == DayOfWeek.Saturday)
return false;
else
return true;
}
/// <summary>
/// 給定時間點加上時間間隔后得出新的時間
/// </summary>
/// <param name="startDate"></param>
/// <param name="exTimeSpan"></param>
/// <param name="time_start"></param>
/// <param name="time_end"></param>
/// <returns></returns>
public static DateTime GetDateTime(DateTime startDate, TimeSpan exTimeSpan, TimeSpan time_start, TimeSpan time_end)
{
TimeSpan t_span = exTimeSpan;
//初始到工作日
while (!IsWorkDay(startDate))
startDate = startDate.AddDays(1);
//初始到起始時間
if (startDate.TimeOfDay < time_start)
startDate = startDate - startDate.TimeOfDay + time_start;
if (startDate.TimeOfDay > time_end)
{
startDate = startDate.AddDays(1);
startDate = startDate - startDate.TimeOfDay + time_start;
//初始到工作日
while (!IsWorkDay(startDate))
startDate = startDate.AddDays(1);
}
//計算本天結束剩余多少天
TimeSpan tmpTs = GetTimeSpan(startDate.TimeOfDay, time_end, time_start, time_end);
//剩余時長
exTimeSpan = exTimeSpan - tmpTs;
//如果計算后剩余小於零 直接返回
if (exTimeSpan < new TimeSpan(0))
return startDate + t_span;
//如果計算后大於零,繼續新增1天.
TimeSpan preDayTimeSpan = time_end - time_start;
do
{
do
{
startDate = startDate.AddDays(1);
} while (!IsWorkDay(startDate));
if (exTimeSpan > preDayTimeSpan)
exTimeSpan -= preDayTimeSpan;
else
break;
} while (exTimeSpan > new TimeSpan(0));
startDate = startDate - startDate.TimeOfDay + time_start; //把計算得出的當天值為初始時間如早上8:00
return startDate + exTimeSpan;
}
}
二段工作時間:如 8:00至12:00 13:00 至17:00
public class TimeHelper2
{
public static TimeSpan GetDateTimeSpan(DateTime dtStart, DateTime dtEnd, TimeSpan time_start, TimeSpan time_end, TimeSpan time_start2, TimeSpan time_end2)
{
if (dtStart.Date == dtEnd.Date) //如果是同一天
{
if (IsWorkDay(dtStart))
return GetTimeSpan(dtStart.TimeOfDay, dtEnd.TimeOfDay, time_start, time_end, time_start2, time_end2);
else
return new TimeSpan(0);
}
//如果不是同一天 計算天數減去1 乘以標准時長 加上分別計算開始開數和結束天數
double days = dtEnd.Date.Subtract(dtStart.Date).TotalDays - 1;
TimeSpan startTimeSpan;
if (IsWorkDay(dtStart))
startTimeSpan = GetTimeSpan(dtStart.TimeOfDay, new TimeSpan(23, 59, 60), time_start, time_end, time_start2, time_end2);//開始天
else
startTimeSpan = new TimeSpan(0);
TimeSpan endTimeSpan;
if (IsWorkDay(dtEnd))
endTimeSpan = GetTimeSpan(new TimeSpan(0, 0, 0), dtEnd.TimeOfDay, time_start, time_end, time_start2, time_end2);//結束天
else
endTimeSpan = new TimeSpan(0);
TimeSpan totalTimeSpan = startTimeSpan + endTimeSpan; //總值
TimeSpan preTimeSpan = GetTimeSpan(new TimeSpan(0, 0, 0), new TimeSpan(23, 59, 60), time_start, time_end, time_start2, time_end2);//開始天
for (int i = 1; i <= days; i++)
{
if (IsWorkDay(dtStart.AddDays(i)))
totalTimeSpan += preTimeSpan; //添加間隔天
}
return totalTimeSpan;
}
/// <summary>
/// 判斷是否為工作日
/// </summary>
/// <param name="dt"></param>
/// <returns></returns>
public static bool IsWorkDay(DateTime dt)
{
//先從日期表中,查找不是上班時間,如果不是直接返回 false ,如果是,直接返回 true。
//如果在日期表中,找不到,則查找定義的日歷,依據日歷定義的周末時間來定義是否為工作日。
//獲取日歷中不上班的標准周末時間,判斷是不是上班時間
if (dt.DayOfWeek == DayOfWeek.Sunday || dt.DayOfWeek == DayOfWeek.Saturday)
return false;
else
return true;
}
//同一天獲取
public static TimeSpan GetTimeSpan(TimeSpan tsStart, TimeSpan tsEnd, TimeSpan time_start, TimeSpan time_end, TimeSpan time_start2, TimeSpan time_end2)
{
//判斷 開始時間
if (tsStart < time_start)
{
//標准開始時間不變
//start1 不變
//start2 不變
}
else if (tsStart >= time_start && tsStart <= time_end)
{
//標准開始= dtStart
time_start = tsStart;
//start1 變
//start2 不變
}
else if (tsStart > time_end && tsStart < time_start2)
{
time_start = time_end;
//start1 變
//start2 不變
}
else if (tsStart >= time_start2 && tsStart <= time_end2)
{
time_start = time_end;
time_start2 = tsStart;
//start1 變
//start2 變
}
else if (tsStart > time_end2)
{
time_start = time_end;
time_start2 = time_end2;
//start1 變
//start2 變
}
//判斷 結束時間
if (tsEnd < time_start)
{
//標准開始時間不變
time_end = time_start;
time_end2 = time_start2;
//time_end 變
//time_end2變
}
else if (tsEnd >= time_start && tsEnd <= time_end)
{
time_end = tsEnd;
time_end2 = time_start2;
//time_end 變
//time_end2變
}
else if (tsEnd > time_end && tsEnd < time_start2)
{
time_end2 = time_start2;
//time_end2 不變
//time_end1變
}
else if (tsEnd >= time_start2 && tsEnd <= time_end2)
{
time_end2 = tsEnd;
//time_end 不變
//time_end2變
}
else if (tsEnd > time_end2)
{
//time_end 不變
//time_end2不變
}
return (time_end - time_start) + (time_end2 - time_start2);
}
}
三個時間段的 如工作時間為://8:30-12:00 13.30-17.30 18.00-21.00
public class TimeHelper3
{
public static TimeSpan GetDateTimeSpan(DateTime dtStart, DateTime dtEnd, TimeSpan time_start, TimeSpan time_end, TimeSpan time_start2, TimeSpan time_end2, TimeSpan time_start3, TimeSpan time_end3)
{
if (dtStart.Date == dtEnd.Date) //如果是同一天
{
if (IsWorkDay(dtStart))
return GetTimeSpan(dtStart.TimeOfDay, dtEnd.TimeOfDay, time_start, time_end, time_start2, time_end2, time_start3, time_end3);
else
return new TimeSpan(0);
}
//如果不是同一天 計算天數減去1 乘以標准時長 加上分別計算開始開數和結束天數
double days = dtEnd.Date.Subtract(dtStart.Date).TotalDays - 1;
TimeSpan startTimeSpan;
if (IsWorkDay(dtStart))
startTimeSpan = GetTimeSpan(dtStart.TimeOfDay, new TimeSpan(23, 59, 60), time_start, time_end, time_start2, time_end2, time_start3, time_end3);//開始天
else
startTimeSpan = new TimeSpan(0);
TimeSpan endTimeSpan;
if (IsWorkDay(dtEnd))
endTimeSpan = GetTimeSpan(new TimeSpan(0, 0, 0), dtEnd.TimeOfDay, time_start, time_end, time_start2, time_end2, time_start3, time_end3);//結束天
else
endTimeSpan = new TimeSpan(0);
TimeSpan totalTimeSpan = startTimeSpan + endTimeSpan; //總值
TimeSpan preTimeSpan = GetTimeSpan(new TimeSpan(0, 0, 0), new TimeSpan(23, 59, 60), time_start, time_end, time_start2, time_end2, time_start3, time_end3);//開始天
for (int i = 1; i <= days; i++)
{
if (IsWorkDay(dtStart.AddDays(i)))
totalTimeSpan += preTimeSpan; //添加間隔天
}
return totalTimeSpan;
}
/// <summary>
/// 判斷是否為工作日
/// </summary>
/// <param name="dt"></param>
/// <returns></returns>
public static bool IsWorkDay(DateTime dt)
{
//先從日期表中,查找不是上班時間,如果不是直接返回 false ,如果是,直接返回 true。
//如果在日期表中,找不到,則查找定義的日歷,依據日歷定義的周末時間來定義是否為工作日。
//獲取日歷中不上班的標准周末時間,判斷是不是上班時間
if (dt.DayOfWeek == DayOfWeek.Sunday || dt.DayOfWeek == DayOfWeek.Saturday)
return false;
else
return true;
}
//同一天獲取
public static TimeSpan GetTimeSpan(TimeSpan tsStart, TimeSpan tsEnd, TimeSpan time_start, TimeSpan time_end, TimeSpan time_start2, TimeSpan time_end2, TimeSpan time_start3, TimeSpan time_end3)
{
//判斷 開始時間
if (tsStart < time_start)
{
//標准開始時間不變
//start1 不變
//start2 不變
//start3 不變
}
else if (tsStart >= time_start && tsStart <= time_end)
{
//標准開始= dtStart
time_start = tsStart;
//start1 變
//start2 不變
//start3 不變
}
else if (tsStart > time_end && tsStart < time_start2)
{
time_start = time_end;
//start1 變
//start2 不變
//start3 不變
}
else if (tsStart >= time_start2 && tsStart <= time_end2)
{
time_start = time_end;
time_start2 = tsStart;
//start1 變
//start2 變
//start3 不變
}
else if (tsStart > time_end2 && tsStart < time_start3)
{
time_start = time_end;
time_start2 = time_end2;
//start1 變
//start2 變
//start3 不變
}
else if (tsStart >= time_start3 && tsStart <= time_end3)
{
time_start = time_end;
time_start2 = time_end2;
time_start3 = tsStart;
//start1 變
//start2 變
//start3 變
}
else if (tsStart > time_end3)
{
time_start = time_end;
time_start2 = time_end2;
time_start3 = time_end3;
}
//判斷 結束時間
if (tsEnd < time_start)
{
//標准開始時間不變
time_end = time_start;
time_end2 = time_start2;
time_end3 = time_start3;
//time_end 變
//time_end2變
//time_end3變
}
else if (tsEnd >= time_start && tsEnd <= time_end)
{
time_end = tsEnd;
time_end2 = time_start2;
time_end3 = time_start3;
//time_end 變
//time_end2變
//time_end3變
}
else if (tsEnd > time_end && tsEnd < time_start2)
{
time_end2 = time_start2;
time_end3 = time_start3;
//time_end1 不變
//time_end2變
//time_end3變
}
else if (tsEnd >= time_start2 && tsEnd <= time_end2)
{
time_end2 = tsEnd;
time_end3 = time_start3;
//time_end 不變
//time_end2變
//time_end3變
}
else if (tsEnd > time_end2 && tsEnd < time_start3)
{
time_end3 = time_start3;
//time_end 不變
//time_end2不變
//time_end3變
}
else if (tsEnd >= time_start3 && tsEnd <= time_end3)
{
time_end3 = tsEnd;
//time_end 不變
//time_end2不變
//time_end3變
}
else if (tsEnd > time_end3)
{
//time_end 不變
//time_end2不變
//time_end3不變
}
return (time_end - time_start) + (time_end2 - time_start2) + (time_end3 - time_start3);
}
}
使用方法:
static void Main(string[] args)
{
DateTime dt = Convert.ToDateTime("2014-04-17 08:00");
DateTime dt2 = Convert.ToDateTime("2014-04-21 08:00");
TimeSpan tsStar1 = new TimeSpan(8, 0, 0);
TimeSpan tsEnd1 = new TimeSpan(12, 0, 0);
TimeSpan tsStar2 = new TimeSpan(13, 0, 0);
TimeSpan tsEnd2 = new TimeSpan(17, 0, 0);
TimeSpan tsStar3 = new TimeSpan(18, 0, 0);
TimeSpan tsEnd3 = new TimeSpan(21, 0, 0);
//8:30-12:00 13.30-17.30 18.00-21.00
TimeSpan ts1 = TimeHelper.GetDateTimeSpan(dt, dt2, tsStar1, tsEnd1);
TimeSpan ts2 = TimeHelper2.GetDateTimeSpan(dt, dt2, tsStar1, tsEnd1, tsStar2, tsEnd2);
TimeSpan ts3 = TimeHelper3.GetDateTimeSpan(dt, dt2, tsStar1, tsEnd1, tsStar2, tsEnd2, tsStar3, tsEnd3);
Console.WriteLine("一階段:{0}天 {1}小時,{2}分,{3}秒", ts1.Days, ts1.Hours, ts1.Minutes, ts1.Seconds);
Console.WriteLine("兩階段:{0}天 {1}小時,{2}分,{3}秒", ts2.Days, ts2.Hours, ts2.Minutes, ts2.Seconds);
Console.WriteLine("三階段:{0}天 {1}小時,{2}分,{3}秒", ts3.Days, ts3.Hours, ts3.Minutes, ts3.Seconds);
Console.ReadLine();
}

