I have a Flags Enum:
[Flags]
public enum WeekDays
{
Monday = 1,
Tuesday = 2,
Wednesday = 4,
Thursday = 8,
Friday = 16,
Saturday = 32,
Sunday = 64
}
and then a class
public class Task
{
public Task()
{
}
public int Days { get; set; }
public TimeSpan Start { get; set; }
public TimeSpan End { get; set; }
}
Assuming the following values
Task task = new Task();
task.Days = 7; // from WeekDays enum: 7 = Monday, Tuesday, Wednesday
task.Start = TimeSpan.Parse("00:00"); //midnight
task.End = TimeSpan.Parse("06:00"); //morning 06 AM
and a specific range period:
DateTime now = DateTime.Now;
DateTime start = now.AddDays(-6);
TimeSpan time = now - start;
double toatlSeconds = time.TotalSeconds; // get total seconds between the start and now datetime range
How can substract from the totalSeconds
the task's totalSeconds
?
So basically I want to exclude from the totalSeconds the period when the task occures which is every Monday, Tuesday, Wednesday between 00:00 and 06:00 which is 3x6hours = 18 hours which is 64800 seconds?
I need to do this by applying the mask to the time range ...
This should be what you are looking for. I decided to rename your class because there is already a Task
class in C#. Also I made it have factory method for creation as you want to do some checks on the values. Also note the need for a mapping from the DayOfWeek
enum used by DateTime
to your WeekDays
enum. Basically you need to iterate through each day that exists between the two DateTime
s to see how much time should be removed from the total duration.
public class ScheduledTask
{
private ScheduledTask() { }
public static ScheduledTask CreateTask(TimeSpan start, TimeSpan end, WeekDays days)
{
if (start < TimeSpan.Zero || start >= TimeSpan.FromDays(1))
{
throw new ArgumentOutOfRangeException("start");
}
if (end < TimeSpan.Zero || end >= TimeSpan.FromDays(1))
{
throw new ArgumentOutOfRangeException("end");
}
if (start > end)
{
throw new ArgumentException("End cannot be before Start", "end");
}
if ((int)days < 1 || (int)days >= 128)
{
throw new ArgumentOutOfRangeException("days");
}
return new ScheduledTask { Start = start, End = end, Days = days };
}
public WeekDays Days { get; private set; }
public TimeSpan Start { get; private set; }
public TimeSpan End { get; private set; }
public TimeSpan DifferenceMinusTaskTime(DateTime from, DateTime to)
{
var actualFrom = from;
var actualTo = to;
if (from > to)
{
actualFrom = to;
actualTo = from;
}
TimeSpan duration = TimeSpan.Zero;
DateTime dayStart = actualFrom;
DateTime dayEnd = actualFrom.Date == actualTo.Date
? actualTo
: actualFrom.Date.AddDays(1);
bool endIsNextDay = dayEnd.Date > dayStart.Date;
while (dayStart < actualTo)
{
duration += dayEnd - dayStart;
if (Days.HasFlag(mapping[dayStart.DayOfWeek])
&& dayStart.TimeOfDay < End
&& (dayEnd.TimeOfDay > Start || endIsNextDay))
{
if (dayStart.TimeOfDay < Start)
{
if (dayEnd.TimeOfDay > End || endIsNextDay)
{
duration -= End - Start;
}
else
{
duration -= dayEnd.TimeOfDay - Start;
}
}
else
{
if (dayEnd.TimeOfDay > End || endIsNextDay)
{
duration -= End - dayStart.TimeOfDay;
}
else
{
duration -= dayEnd - dayStart;
}
}
}
dayStart = dayEnd;
dayEnd = dayStart.Date == actualTo.Date
? actualTo
: dayStart.Date.AddDays(1);
endIsNextDay = dayEnd.Date > dayStart.Date;
}
return from > to ? TimeSpan.Zero - duration : duration;
}
private Dictionary<DayOfWeek, WeekDays> mapping =
new Dictionary<DayOfWeek, WeekDays>
{
{ DayOfWeek.Monday, WeekDays.Monday },
{ DayOfWeek.Tuesday, WeekDays.Tuesday },
{ DayOfWeek.Wednesday, WeekDays.Wednesday },
{ DayOfWeek.Thursday, WeekDays.Thursday },
{ DayOfWeek.Friday, WeekDays.Friday },
{ DayOfWeek.Saturday, WeekDays.Saturday },
{ DayOfWeek.Sunday, WeekDays.Sunday }
};
}
With the above the following
var task = ScheduledTask.CreateTask(
TimeSpan.FromHours(2),
TimeSpan.FromHours(8),
WeekDays.Monday | WeekDays.Tuesday | WeekDays.Wednesday);
Console.WriteLine(
task.DifferenceMinusTaskTime(
new DateTime(2015, 8, 24),
new DateTime(2015, 8, 27))); // 2 days 6 hours
Console.WriteLine(
task.DifferenceMinusTaskTime(
new DateTime(2015, 8, 27),
new DateTime(2015, 8, 24))); // -2 days 6 hours
Console.WriteLine(
task.DifferenceMinusTaskTime(
new DateTime(2015, 8, 28),
new DateTime(2015, 8, 29))); // 1 day
Console.WriteLine(
task.DifferenceMinusTaskTime(
new DateTime(2015, 8, 24),
new DateTime(2015, 8, 24, 10, 0, 0))); // 4 hours
Console.WriteLine(
task.DifferenceMinusTaskTime(
new DateTime(2015, 8, 24),
new DateTime(2015, 8, 24, 4, 0, 0))); // 2 hours
Console.WriteLine(
task.DifferenceMinusTaskTime(
new DateTime(2015, 8, 24, 4, 0, 0),
new DateTime(2015, 8, 24, 6, 0, 0))); // 0 hours
Console.WriteLine(
task.DifferenceMinusTaskTime(
new DateTime(2015, 8, 24, 4, 0, 0),
new DateTime(2015, 8, 24, 10, 0, 0))); // 2 hours
Console.WriteLine(
task.DifferenceMinusTaskTime(
new DateTime(2015, 8, 24, 10, 0, 0),
new DateTime(2015, 8, 24, 14, 0, 0))); // 4 hours
will output
2.06:00:00
-2.06:00:00
1.00:00:00
04:00:00
02:00:00
00:00:00
02:00:00
04:00:00
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With