我需要确定两个DateTimes之间的持续时间,以分钟为单位。
然而,有一点点扭曲:
[09/30/2010 6:39:00
PM] - [09/30/2010 7:39:00 PM] = 21
Minutes
我只是很难想出一个体面的方式来做这件事,如果有人能提出建议,我会很感激。
感谢。
编辑:
我最终选择了dtb的解决方案。只有一个特殊情况需要注意:如果结束时间是晚上7点之后,则计算从上午7点到实际结束时间的分钟数。
这是我修改它的方式:
var minutes = from day in start.DaysInRangeUntil(end)
where !day.IsWeekendDay()
let st = Helpers.Max(day.AddHours(7), start)
let en = (day.DayOfYear == end.DayOfYear ?
end :
Helpers.Min(day.AddHours(19), end)
)
select (en - st).TotalMinutes;
再次感谢您的帮助。
答案 0 :(得分:23)
当然,您可以使用LINQ:
DateTime a = new DateTime(2010, 10, 30, 21, 58, 29);
DateTime b = a + new TimeSpan(12, 5, 54, 24, 623);
var minutes = from day in a.DaysInRangeUntil(b)
where !day.IsWeekendDay()
let start = Max(day.AddHours( 7), a)
let end = Min(day.AddHours(19), b)
select (end - start).TotalMinutes;
var result = minutes.Sum();
// result == 6292.89
(注意:您可能需要检查我完全忽略的很多极端情况。)
助手方法:
static IEnumerable<DateTime> DaysInRangeUntil(this DateTime start, DateTime end)
{
return Enumerable.Range(0, 1 + (int)(end.Date - start.Date).TotalDays)
.Select(dt => start.Date.AddDays(dt));
}
static bool IsWeekendDay(this DateTime dt)
{
return dt.DayOfWeek == DayOfWeek.Saturday
|| dt.DayOfWeek == DayOfWeek.Sunday;
}
static DateTime Max(DateTime a, DateTime b)
{
return new DateTime(Math.Max(a.Ticks, b.Ticks));
}
static DateTime Min(DateTime a, DateTime b)
{
return new DateTime(Math.Min(a.Ticks, b.Ticks));
}
答案 1 :(得分:5)
记下你的开始时间,得到那天结束的分钟数(即晚上7点)。
然后从第二天早上7点开始计算最后一天的天数(不包括截至结束日期的任何时间)。
计算已经过了多少(如果有的话)周末。 (对于每个周末,将天数减少2)。
从那里做一些简单的数学计算得出天数的总分钟数。
在最后一天和开始日加时间添加额外时间。
答案 2 :(得分:4)
尝试以下DiffRange功能。
public static DateTime DayStart(DateTime date)
{
return date.Date.AddHours(7);
}
public static DateTime DayEnd(DateTime date)
{
return date.Date.AddHours(19);
}
public static TimeSpan DiffSingleDay(DateTime start, DateTime end)
{
if ( start.Date != end.Date ) {
throw new ArgumentException();
}
if (start.DayOfWeek == DayOfWeek.Saturday || start.DayOfWeek == DayOfWeek.Sunday )
{
return TimeSpan.Zero;
}
start = start >= DayStart(start) ? start : DayStart(start);
end = end <= DayEnd(end) ? end : DayEnd(end);
return end - start;
}
public static TimeSpan DiffRange(DateTime start, DateTime end)
{
if (start.Date == end.Date)
{
return DiffSingleDay(start, end);
}
var firstDay = DiffSingleDay(start, DayEnd(start));
var lastDay = DiffSingleDay(DayStart(end), end);
var middle = TimeSpan.Zero;
var current = start.AddDays(1);
while (current.Date != end.Date)
{
middle = middle + DiffSingleDay(current.Date, DayEnd(current.Date));
current = current.AddDays(1);
}
return firstDay + lastDay + middle;
}
答案 3 :(得分:1)
我确信我错过了一些东西。
TimeSpan CalcBusinessTime(DateTime a, DateTime b)
{
if (a > b)
{
DateTime tmp = a;
a = b;
b = tmp;
}
if (a.TimeOfDay < new TimeSpan(7, 0, 0))
a = new DateTime(a.Year, a.Month, a.Day, 7, 0, 0);
if (b.TimeOfDay > new TimeSpan(19, 0, 0))
b = new DateTime(b.Year, b.Month, b.Day, 19, 0, 0);
TimeSpan sum = new TimeSpan();
TimeSpan fullDay = new TimeSpan(12, 0, 0);
while (a < b)
{
if (a.DayOfWeek != DayOfWeek.Saturday && a.DayOfWeek != DayOfWeek.Sunday)
{
sum += (b - a < fullDay) ? b - a : fullDay;
}
a = a.AddDays(1);
}
return sum;
}
答案 4 :(得分:1)
这是一个非常难的问题。对于一个基本的,直截了当的方法,我写了下面的代码:
DateTime start = new DateTime(2010, 01, 01, 21, 00, 00);
DateTime end = new DateTime(2010, 10, 01, 14, 00, 00);
// Shift start date's hour to 7 and same for end date
// These will be added after doing calculation:
double startAdjustmentMinutes = (start - start.Date.AddHours(7)).TotalMinutes;
double endAdjustmentMinutes = (end - end.Date.AddHours(7)).TotalMinutes;
// We can do some basic
// mathematical calculation to find weekdays count:
// divide by 7 multiply by 5 gives complete weeks weekdays
// and adding remainder gives the all weekdays:
int weekdaysCount = (((int)((end.Date - start.Date).Days / 7) * 5)
+ ((end.Date - start.Date).Days % 7));
// so we can multiply it by minutes between 7am to 7 pm
int minutes = weekdaysCount * (12 * 60);
// after adding adjustment we have the result:
int result = minutes + startAdjustmentMinutes + endAdjustmentMinutes;
我知道这在程序上并不美观,但我不知道在开始和结束之间迭代几天和几小时是否合适。
答案 5 :(得分:1)
static int WorkPeriodMinuteDifference(DateTime start, DateTime end)
{
//easier to only have to work in one direction.
if(start > end)
return WorkPeriodMinuteDifference(end, start);
//if weekend, move to start of next Monday.
while((int)start.DayOfWeek % 6 == 0)
start = start.Add(new TimeSpan(1, 0, 0, 0)).Date;
while((int)end.DayOfWeek % 6 == 0)
end = end.Add(new TimeSpan(1, 0, 0, 0)).Date;
//Move up to 07:00 or down to 19:00
if(start.TimeOfDay.Hours < 7)
start = new DateTime(start.Year, start.Month, start.Day, 7, 0, 0);
else if(start.TimeOfDay.Hours > 19)
start = new DateTime(start.Year, start.Month, start.Day, 19, 0, 0);
if(end.TimeOfDay.Hours < 7)
end = new DateTime(end.Year, end.Month, end.Day, 7, 0, 0);
else if(end.TimeOfDay.Hours > 19)
end = new DateTime(end.Year, end.Month, end.Day, 19, 0, 0);
TimeSpan difference = end - start;
int weeks = difference.Days / 7;
int weekDays = difference.Days % 7;
if(end.DayOfWeek < start.DayOfWeek)
weekDays -= 2;
return (weeks * 5 * 12 * 60) + (weekDays * 12 * 60) + difference.Hours * 60 + difference.Minutes
}
答案 6 :(得分:1)
我的实施:)我们的想法是快速计算总周数,并逐日走完剩余的一周......
public TimeSpan Compute(DateTime start, DateTime end)
{
// constant start / end times per day
TimeSpan sevenAM = TimeSpan.FromHours(7);
TimeSpan sevenPM = TimeSpan.FromHours(19);
if( start >= end )
{
throw new Exception("invalid date range");
}
// total # of weeks
int completeWeeks = ((int)(end - start).TotalDays) / 7;
// starting total
TimeSpan total = TimeSpan.FromHours(completeWeeks * 12 * 5);
// adjust the start date to be exactly "completeWeeks" past its original start
start = start.AddDays(completeWeeks * 7);
// walk days from the adjusted start to end (at most 7), accumulating time as we can...
for(
// start at midnight
DateTime dt = start.Date;
// continue while there is time left
dt < end;
// increment 1 day at a time
dt = dt.AddDays(1)
)
{
// ignore weekend
if( (dt.DayOfWeek == DayOfWeek.Saturday) ||
(dt.DayOfWeek == DayOfWeek.Sunday) )
{
continue;
}
// get the start/end time for each day...
// typically 7am / 7pm unless we are at the start / end date
TimeSpan dtStartTime = ((dt == start.Date) && (start.TimeOfDay > sevenAM)) ?
start.TimeOfDay : sevenAM;
TimeSpan dtEndTime = ((dt == end.Date) && (end.TimeOfDay < sevenPM)) ?
end.TimeOfDay : sevenPM;
if( dtStartTime < dtEndTime )
{
total = total.Add(dtEndTime - dtStartTime);
}
}
return total;
}
答案 7 :(得分:1)
使用TimeSpan.TotalMinutes,减去非工作日,减去多余的时间。
答案 8 :(得分:0)
我不会写任何代码,但有一个DateTime你可以告诉星期几,因此你知道你的范围内有多少个周末,所以你可以知道周末有多少分钟。
所以它不会那么难......当然必须有一个最佳的单线解决方案......但我认为你可以解决这个问题。
我忘了提到你也知道晚上7点到早上7点之间的会议纪要,所以你所要做的就是减去你得到的时差所需的分钟数。