Calculate number of minutes between configurable hours - c#

I have a Journey object that has a DateTime JourneyStartTime { get; set; } and a DateTime JourneyEndTime { get; set; }. I want to calculate the total number of minutes that the journey spent between 10pm and 6am (note this goes over midnight).
I have tried using TimeSpans for indicating the 10pm and 6am, but I am not sure if that is the best data type to use.
The domain for this logic is insurance based. Company X wants to score drivers that drive between X - Y hours. Those hours ought to be configurable. Here's a scenario:
A journey takes place on the same day between 5pm and 6pm. Company X Inurance is interested in journeys between 10pm and 6am. How many minutes did that journey spend in the time period that Company X is interested in?
The answer to the above is: 0, but my code is giving 60 minutes (here is a dotnetFiddle).
Here is the code.
CODE
using System;
public class Program
{
public static void Main()
{
var shortSameDayJourney = new Journey {
JourneyId = 1,
// start of journey - 5pm - start
JourneyStartTime = new DateTime(2018, 12, 17, 17, 00, 00, DateTimeKind.Utc),
// end of journey - 6pm - end
JourneyEndTime = new DateTime(2018, 12, 17, 18, 00, 00, DateTimeKind.Utc)
};
var scoreTimePeriod = new InsurerTimePeriodScoreSetting {
// start of insurer's time period.
StartOfTimePeriod = DateTime.Now + TimeSpan.FromHours(22),
// end of insurer's time period.
EndOfTimePeriod = DateTime.Now + TimeSpan.FromHours(30)
};
var minutesInTimePeriod = getNumberOfMinutesThatJourneyWasInTimePeriod(shortSameDayJourney, scoreTimePeriod);
Console.WriteLine("Number of minutes the journey was within the time period the insurer had sepcified:");
Console.WriteLine(minutesInTimePeriod + " minutes");
}
public static double getNumberOfMinutesThatJourneyWasInTimePeriod(
Journey journey,
InsurerTimePeriodScoreSetting insurerTimePeriod) {
var JourneyStart = journey.JourneyStartTime;
var JourneyEnd = journey.JourneyEndTime;
var timeSpan = insurerTimePeriod.EndOfTimePeriod - insurerTimePeriod.StartOfTimePeriod;
var startDif = (JourneyStart - insurerTimePeriod.StartOfTimePeriod);
var endDif = (insurerTimePeriod.EndOfTimePeriod - JourneyEnd);
var time = timeSpan - startDif - endDif;
return time.TotalMinutes;
}
}
public class Journey {
public int JourneyId {get;set;}
// journey start date and time in UTC, comes form a tracking device on vehicle.
public DateTime JourneyStartTime {get;set;}
// journey end date and time in UTC, comes form a tracking device on vehicle.
public DateTime JourneyEndTime {get;set;}
}
public class InsurerTimePeriodScoreSetting {
public DateTime StartOfTimePeriod {get;set;}
public DateTime EndOfTimePeriod {get;set;}
}

Timespan only gives your raw time between 2 DateTime's
so i had to changed your Journey initialization so i will be able to compare on the same day
var shortSameDayJourney = new Journey
{
JourneyId = 1,
// start of journey - 5pm - start
JourneyStartTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 17, 00, 00, DateTimeKind.Utc),
// end of journey - 6pm - end
JourneyEndTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 18, 00, 00, DateTimeKind.Utc)
};
same for InsurerTimePeriodScoreSetting
var scoreTimePeriod = new InsurerTimePeriodScoreSetting
{
// start of insurer's time period. 18/12 22:00
StartOfTimePeriod = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 22, 0, 0, DateTimeKind.Utc), // DateTime.Now + TimeSpan.FromHours(22),
// end of insurer's time period. 19/12 6:00
EndOfTimePeriod = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day + 1, 6, 0, 0, DateTimeKind.Utc) // DateTime.Now + TimeSpan.FromHours(30)
};
now all you need to do is a simple check - if Journey time is between InsurerTimePeriodScoreSetting
if (JourneyStart >= insurerTimePeriod.StartOfTimePeriod && JourneyEnd <= insurerTimePeriod.EndOfTimePeriod)
{
// your same calculation here
}
else
return 0;

Related

How to get interval between hours and put into list from start into finish?

For example, I will be given a time on hours with type DateTime hours like this
for the starter
my starttime is 00:00
endtime is 02:00
and every time 30 minutes I like to input the value into a List<DateTime>
so, how can I get the value to put into a list that is look like this?
00:00
00:30
01:00
01:30
02:00
My Code
DateTime starTime = new DateTime();
DateTime endTimes = new DateTime();
DateTime interval = new DateTime();
List<DateTime> intervals = new List<DateTime>();
starTime = DateTime.ParseExact(fulldate + "00:00",
"yyyy/MM/dd HH:mm",
CultureInfo.InvariantCulture);
endTimes = DateTime.ParseExact(fulldate + "02:00",
"yyyy/MM/dd HH:mm",
CultureInfo.InvariantCulture); ;
interval = starTime;
for (int i = 0; i < 24; i++)
{
interval.AddHours(0.5);
intervals.Add(interval);
if (interval.ToString("HH:mm") == endTimes.ToString("HH:mm"))
{
break;
}
}
Can anyone help me to solve this?
With some assumption (that end time is on the same day, that your end time is always something that can be devided by 30 mins, ...) this would work.
var start = new TimeSpan(0, 0, 0);
var end = new TimeSpan(2, 0, 0);
var current = start;
List<DateTime> values = new List<DateTime>();
var startDate = DateTime.Now.Date; // editited after #pinkflowydx33's comment
values.Add(startDate + start);
while (current < end)
{
current = current.Add(new TimeSpan(0, 30, 0));
values.Add(startDate + current);
}
foreach (var v in values)
{
Console.WriteLine(v);
}
i prepared that type of solution. - It's loop over number, which represent - times of valueToChange - in this specific case between 30 minutes - and add to the startDate - 30 minutes and also saving to list.
using System;
public class Program
{
public static void Main()
{
List<DateTime> intervals = new List<DateTime>();
var changeValue = 30;
var startDate = new DateTime(2010, 05, 12, 13, 00, 00);
var endDate = new DateTime(2010, 05, 12, 14, 00, 00);
var timeIntervals = System.Math.Abs(startDate.Subtract(endDate).TotalMinutes / changeValue);
for (int i = 0; i < timeIntervals; i++)
{
startDate.AddMinutes(30);
intervals.Add(startDate)
}
}
}
In this case the start and end date are divided by 30 minutes without rest - so if there will be 13:00 and 13:12 - it's doesn't add the value to List - cause the value doesn't > 30.

Find hole in schedule

I’m looking for a way to find holes in a schedule, times that does not have a booking.
I have a simple class in C# that looks like:
DateTime StartTime { get; set; }
Datetime EndTime { get; set; }
public int User_ID { get; set; }
The same class is used for the bookings aswell.
Let’s assume I have these objects:
Schedule: StartTime "2017-03-14 08:00" - EndTime "2017-03-14 16:00" (8 hours)
Booking: StartTime "2017-03-14 09:00" - Endtime "2017-03-14 10:00" (1 hour)
My final result from this would be 2 objects that represents the “free time”:
Free: StartTime "2017-03-14 08:00" EndTime: "2017-03-14 09:00" (1 hour)
Free: StartTime "2017-03-14 10:00" EndTime: "2017-03-14 16:00"(6 hour)
How would I check this in C#?
I'm thinking about looping the Schedule and split them on start/end of each booking, but I'm not sure how to do it.
It is easier than I thought... Note that this code isn't optimized, and this algorithm isn't probably very optimizable:
public class TimeSegment
{
public readonly DateTime StartTime;
public readonly DateTime EndTime;
public TimeSegment(DateTime startTime, DateTime endTime)
{
StartTime = startTime;
EndTime = endTime;
}
public TimeSegment[] Subtract(TimeSegment other)
{
// 8-10 Subtract 10-11 = 8-10
if (StartTime > other.EndTime || other.StartTime > EndTime)
{
// If there is no intersection, we return { this }
// (no subtraction)
return new[] { this };
}
if (StartTime >= other.StartTime)
{
// 8-10 Subtract 8-10 = (nothing)
// 8-10 Subtract 7-11 = (nothing)
if (EndTime <= other.EndTime)
{
// Total subtraction, nothing remains!
return new TimeSegment[0];
}
else
{
// 8-10 Subtract 7-9 = 9-10
return new[] { new TimeSegment(other.EndTime, EndTime) };
}
}
// 8-12 Subtract 9-13 = 8-9
if (EndTime <= other.EndTime)
{
return new[] { new TimeSegment(StartTime, other.EndTime) };
}
// 8-12 Subtract 9-11 = 8-9, 11-12
// Complete case: two TimeSegments returned
return new[] { new TimeSegment(StartTime, other.StartTime), new TimeSegment(other.EndTime, EndTime) };
}
public override string ToString()
{
return string.Format("{0}-{1}", StartTime, EndTime);
}
}
And then:
var schedules = new List<TimeSegment> { new TimeSegment(new DateTime(2017, 03, 14, 08, 00, 00), new DateTime(2017, 03, 14, 16, 00, 00)) };
var bookings = new List<TimeSegment>
{
new TimeSegment(new DateTime(2017, 03, 14, 09, 00, 00), new DateTime(2017, 03, 14, 10, 00, 00)),
new TimeSegment(new DateTime(2017, 03, 14, 12, 00, 00), new DateTime(2017, 03, 14, 14, 00, 00)),
new TimeSegment(new DateTime(2017, 03, 14, 13, 00, 00), new DateTime(2017, 03, 14, 15, 00, 00)),
};
foreach (TimeSegment booking in bookings)
{
var schedulesNew = new List<TimeSegment>();
foreach (TimeSegment schedule in schedules)
{
var diff = schedule.Subtract(booking);
schedulesNew.AddRange(diff);
}
schedules = schedulesNew;
}
There "core" of this is a Subtract function that given a TimeSegment subtracts from this another TimeSegment, returning 0, 1 or 2 TimeSegments... Then iteratively we subtract all the bookings from the TimeSegments that we produced from the previous booking.

Get total hours that fall between a specific time period

the condition is Time in and Time out (e.g 02/01/2015 02:55 'til 02/02/2015 05:55) that is more than a day. I already computed the total hours of Time in and Time out, and I want to know if the total hours has passed between 23:00(11:00PM ) up to 06:00AM and get the total of it
var hours = (datevalue1 - datevalue2).TotalHours;
or
Timespace ts= (datevalue1 - datevalue2);
var hours = ts.Value.TotalHours;
Try this way.. DateTime.Parse().Subtract()
eg:
string startTime = "11:00 PM";
string endTime = "6:00 AM";
TimeSpan duration = DateTime.Parse(endTime).Subtract(DateTime.Parse(startTime));
Console.WriteLine(duration);
Console.ReadKey();
OR
TimeSpan is the object you need:
TimeSpan span = (DateTime.Now - DateTime.Now);
String.Format("{0} days, {1} hours, {2} minutes, {3} seconds",
span.Days, span.Hours, span.Minutes, span.Seconds);
You can calculate it by passing over time. when its night time add it to TimeSpan.
DateTime timeIn = new DateTime(2015, 09, 29, 10, 11, 3); // 29-09-2015 at 10:11:03
DateTime timeOut = new DateTime(2015, 10, 1, 2, 19, 18); // 01-10-2015 at 02:19:38
TimeSpan nightTime = new TimeSpan(); //total amount of night time
TimeSpan passLength = new TimeSpan(0, 0, 0, 1); // length of time to pass at each iteration (1s)
while (timeIn < timeOut) // do it until timeIn reaches timeOut
{
timeIn = timeIn.Add(passLength); // add 1 second to timeIn
if (timeIn.Hour < 6 || timeIn.Hour == 23) // if we are in range of night time
{
nightTime = nightTime.Add(passLength); // add 1 second to night time
}
}
Console.WriteLine(nightTime);
You can do lot of optimizations. for long times its not good idea to add 1 sec each time. you can add 1 day to TimeIn at each iterate then add only 6 hours to night time. after you get close to Timeout decrease length time
Here is a better way. first get days fast. then get rest of the time.
DateTime timeIn = new DateTime(2015, 09, 29, 10, 11, 3); // 29-09-2015 at 10:11:03
DateTime timeOut = new DateTime(2015, 10, 1, 2, 19, 18); // 01-10-2015 at 02:19:38
// Get days
TimeSpan passLength = new TimeSpan(1, 0, 0, 0); // one day per iterate
while (timeIn + passLength < timeOut)
{
timeIn = timeIn.Add(passLength);
nightTime = nightTime.Add(new TimeSpan(0, 7, 0, 0)); // 7 hours of a day passed is considered night time
}
// Get rest of the time
passLength = new TimeSpan(0, 0, 0, 1); // one second per iterate
while (timeIn < timeOut) // do it until timeIn reaches timeOut
{
timeIn = timeIn.Add(passLength); // add 1 second to timeIn
if (timeIn.Hour < 6 || timeIn.Hour == 23) // if we are in range of night time
{
nightTime = nightTime.Add(passLength); // add 1 second to night time
}
}
Console.WriteLine(nightTime);
You shouldn't be worry about rest of the time calculation performance. since the rest of the time is now less than 1 day which is only 86400 seconds.
Less than 86400 iterates should be fine for today's processors speed. how ever you can still optimize it farther away but you don't get much more performance.
A little bit different and faster approach:
static void Main(string[] args)
{
TimeSpan result = new TimeSpan();
DateTime dt1 = new DateTime(2015, 09, 29, 10, 11, 03);
DateTime dt2 = new DateTime(2015, 10, 01, 02, 19, 38);
DateTime d1 = new DateTime(dt1.Year, dt1.Month, dt1.Day, 0, 0, 0); //Date only
DateTime d2 = new DateTime(dt2.Year, dt2.Month, dt2.Day, 0, 0, 0); //Date only
//Count night time in first day
result += DateTime.Compare(dt1, d1.AddHours(6)) > 0 ? new TimeSpan(6, 0, 0) : new TimeSpan(dt1.Hour, dt1.Minute, dt1.Second);
if (DateTime.Compare(dt1, d1.AddHours(23)) > 0) result += new TimeSpan(dt1.Hour - 23, dt1.Minute, dt1.Second);
//Count night time in last day
result += DateTime.Compare(dt2, d2.AddHours(6)) > 0 ? new TimeSpan(6, 0, 0) : new TimeSpan(dt2.Hour, dt2.Minute, dt2.Second);
if (DateTime.Compare(dt2, d2.AddHours(23)) > 0) result += new TimeSpan(dt1.Hour - 23, dt2.Minute, dt2.Second);
//Count night time in middle days
int daysBetween = (int)(d2 - d1).TotalDays - 1;
result += new TimeSpan(daysBetween * 7, 0, 0);
Console.WriteLine("Night time: " + result);
Console.ReadKey();
}
Compare EndTime with your Range(23:00-06:00)
that is in your Case, check wether EndTime 05:55 < 06:00 and EndTime 05:55 > 23:00
You can subtract the DateTime values to get the TimeSpan in between. Then you can get the TotalHours in that
var hours = timeOut.Subtract(timeIn).TotalHours;
For example
timeIn = 29-09-2015 10:11:03;
timeOut = 01-10-2015 02:19:38;
hours = 52.14303137125;

Date calculations in C#

When given a start date a need to do various calculations on it to produce 3 other dates.
Basically I need to work out what date the user has been billed up to for different frequencies based on the current date.
Bi-Annually (billed twice a year),
Quarterly (billed 4 times a year),
and Two Monthly (billed ever other month).
Take the date 26/04/2008
- BiAnnually: This date would have been last billed on 26/10/2010 and should give the date 26/04/2011.
- Quarterly: This date would have been last billed on 26/01/2011 and should give the date 26/04/2011.
- Two Month: This date would have been last billed on 26/12/2010 and should give the date 26/02/2011.
Assistance is much appreciated.
I think that you can just do like this:
public void FindNextDate(DateTime startDate, int interval);
DateTime today = DateTime.Today;
do {
startDate = startDate.AddMonths(interval);
} while (startDate <= today);
return startDate;
}
Usage:
DateTime startDate = new DateTime(2008, m4, 26);
DateTime bi = FindNextDate(startDate, 6);
DateTime quarterly = FindNextDate(startDate, 3);
DateTime two = FindNextDate(startDate, 2);
I think all you want is something like
DateTime x = YourDateBasis;
y = x.AddMonths(6);
y = x.AddMonths(3);
y = x.AddMonths(2);
Then to edit from comment,
Date Math per the period cycle of the person's account, you would simply need the start and end date and keep adding respective months until you've created all expected months. Almost like that of a loan payment that's due every month for 3 years
DateTime CurrentDate = DateTime.Now;
while( CurrentDate < YourFinalDateInFuture )
{
CurrentDate = CurrentDate.AddMonths( CycleFrequency );
Add Record into your table as needed
Perform other calcs as needed
}
enum BillPeriod
{
TwoMonth = 2,
Quarterly = 3,
SemiAnnually = 6,
BiAnnually = 24
}
public Pair<Datetime, Datetime> BillDates(Datetime currentBillDate, BillPeriod period)
{
Datetime LastBill = currentBillDate.AddMonths(-1 * (int)period);
Datetime NextBill = currentBillDate.AddMonths((int)period);
return new Pair<Datetime,Datetime>(LastBill, NextBill);
}
This is a terrible solution, but it works. Remember, red-light, green-light, refactor. Here, we're at green-light:
namespace ConsoleApplication1 {
class Program {
static void Main(string[] args) {
Console.WriteLine(GetLastBilled(new DateTime(2008, 4, 26), 6));
Console.WriteLine(GetNextBilled(new DateTime(2008, 4, 26), 6));
Console.WriteLine(GetLastBilled(new DateTime(2008, 4, 26), 4));
Console.WriteLine(GetNextBilled(new DateTime(2008, 4, 26), 4));
Console.WriteLine(GetLastBilled(new DateTime(2008, 4, 26), 2));
Console.WriteLine(GetNextBilled(new DateTime(2008, 4, 26), 2));
Console.WriteLine("Complete...");
Console.ReadKey(true);
}
static DateTime GetLastBilled(DateTime initialDate, int billingInterval) {
// strip time and handle staggered month-end and 2/29
var result = initialDate.Date.AddYears(DateTime.Now.Year - initialDate.Year);
while (result > DateTime.Now.Date) {
result = result.AddMonths(billingInterval * -1);
}
return result;
}
static DateTime GetNextBilled(DateTime initialDate, int billingInterval) {
// strip time and handle staggered month-end and 2/29
var result = initialDate.Date.AddYears(DateTime.Now.Year - initialDate.Year);
while (result > DateTime.Now.Date) {
result = result.AddMonths(billingInterval * -1);
}
result = result.AddMonths(billingInterval);
return result;
}
}
}
This is really tricky. For example, you need to take into account that the date you billed could have been 2/29 on a leap year, and not all months have the same number of days. That's why I did the initialDate.Date.AddYears(DateTime.Now.Year - initialDate.Year); call.

Calculating a date around working days/hours?

I am currently working on a website to track projects. In it, it is possible to create Service Level Agreements (SLAs). These are configurable with days of the week that a project can be worked on and also the timespan on each of those days. Eg. on Monday it might be between 08:00 and 16:00 and then on friday from 10:00 to 14:00. They are also configured with a deadline time depending on priority. Eg. a project created with the "Low" priority has a deadline time of two weeks, and a project with "High" priority has a deadline of four hours.
The problem I'm having is calculating the deadline AROUND the hours described earlier. Say I create a project on Monday at 14:00 with a "High" priority. That means I have four hours for this project. But because of the working hours, I have two hours on monday (untill 16:00) and then another two hours on Friday. That means the Deadline must be set for Friday at 12:00.
I've spent quite some time googling this, and I can find quite a few examples of finding out how many working hours there are between a given start end ending date. I just can't figure out how to convert it into FINDING the ending datetime, given a starting time and an amount of time untill the deadline.
The day/timespans are stored in an sql database in the format:
Day(Eg. 1 for Monday) StartHour EndHour
The StartHour/EndHour are saved as DateTimes, but of course only the time part is important.
The way I figure it is, I have to somehow iterate through these times and do some datetime calculations. I just can't quite figure out what those calculations should be, what the best way is.
I found this Question here on the site as I was writing this. It is sort of what I want and I'm playing with it right now, but I'm still lost on how exactly to make it work around my dynamic work days/hours.
Here's some C# code which might help, it could be much cleaner, but it's a quick first draft.
class Program
{
static void Main(string[] args)
{
// Test
DateTime deadline = DeadlineManager.CalculateDeadline(DateTime.Now, new TimeSpan(4, 0, 0));
Console.WriteLine(deadline);
Console.ReadLine();
}
}
static class DeadlineManager
{
public static DateTime CalculateDeadline(DateTime start, TimeSpan workhours)
{
DateTime current = new DateTime(start.Year, start.Month, start.Day, start.Hour, start.Minute, 0);
while(workhours.TotalMinutes > 0)
{
DayOfWeek dayOfWeek = current.DayOfWeek;
Workday workday = Workday.GetWorkday(dayOfWeek);
if(workday == null)
{
DayOfWeek original = dayOfWeek;
while (workday == null)
{
current = current.AddDays(1);
dayOfWeek = current.DayOfWeek;
workday = Workday.GetWorkday(dayOfWeek);
if (dayOfWeek == original)
{
throw new InvalidOperationException("no work days");
}
}
current = current.AddHours(workday.startTime.Hour - current.Hour);
current = current.AddMinutes(workday.startTime.Minute - current.Minute);
}
TimeSpan worked = Workday.WorkHours(workday, current);
if (workhours > worked)
{
workhours = workhours - worked;
// Add one day and reset hour/minutes
current = current.Add(new TimeSpan(1, current.Hour * -1, current.Minute * -1, 0));
}
else
{
current.Add(workhours);
return current;
}
}
return DateTime.MinValue;
}
}
class Workday
{
private static readonly Dictionary<DayOfWeek, Workday> Workdays = new Dictionary<DayOfWeek, Workday>(7);
static Workday()
{
Workdays.Add(DayOfWeek.Monday, new Workday(DayOfWeek.Monday, new DateTime(1, 1, 1, 10, 0, 0), new DateTime(1, 1, 1, 16, 0, 0)));
Workdays.Add(DayOfWeek.Tuesday, new Workday(DayOfWeek.Tuesday, new DateTime(1, 1, 1, 10, 0, 0), new DateTime(1, 1, 1, 16, 0, 0)));
Workdays.Add(DayOfWeek.Wednesday, new Workday(DayOfWeek.Wednesday, new DateTime(1, 1, 1, 10, 0, 0), new DateTime(1, 1, 1, 16, 0, 0)));
Workdays.Add(DayOfWeek.Thursday, new Workday(DayOfWeek.Thursday, new DateTime(1, 1, 1, 10, 0, 0), new DateTime(1, 1, 1, 16, 0, 0)));
Workdays.Add(DayOfWeek.Friday, new Workday(DayOfWeek.Friday, new DateTime(1, 1, 1, 10, 0, 0), new DateTime(1, 1, 1, 14, 0, 0)));
}
public static Workday GetWorkday(DayOfWeek dayofWeek)
{
if (Workdays.ContainsKey(dayofWeek))
{
return Workdays[dayofWeek];
}
else return null;
}
public static TimeSpan WorkHours(Workday workday, DateTime time)
{
DateTime sTime = new DateTime(time.Year, time.Month, time.Day,
workday.startTime.Hour, workday.startTime.Millisecond, workday.startTime.Second);
DateTime eTime = new DateTime(time.Year, time.Month, time.Day,
workday.endTime.Hour, workday.endTime.Millisecond, workday.endTime.Second);
if (sTime < time)
{
sTime = time;
}
TimeSpan span = eTime - sTime;
return span;
}
public static DayOfWeek GetNextWeekday(DayOfWeek dayOfWeek)
{
int i = (dayOfWeek == DayOfWeek.Saturday) ? 0 : ((int)dayOfWeek) + 1;
return (DayOfWeek)i;
}
private Workday(DayOfWeek dayOfWeek, DateTime start, DateTime end)
{
this.dayOfWeek = dayOfWeek;
this.startTime = start;
this.endTime = end;
}
public DayOfWeek dayOfWeek;
public DateTime startTime;
public DateTime endTime;
}
There's a recursive solution that could work, try thinking along these lines:
public DateTime getDeadline(SubmitTime, ProjectTimeAllowed)
{
if (SubmitTime+ProjectTimeAllowed >= DayEndTime)
return getDeadline(NextDayStart, ProjectTimeAllowed-DayEndTime-SubmitTime)
else
return SubmitTime + ProjectTimeAllowed
}
Obviously this is quite rough pseudocode. Hopefully it just gives you another way to think about the problem.
Here's how I would do it. The algorithm is to see whether the issue can be closed today and if not, use all of today's time to reduce the issue's remaining time and go to tomorrow.
Find the time you have to close the issue as a TimeSpan (I'm calling this the issue's remaining time)
For each working day, create a DateTime that has only the time of the start and end.
Set the start time to now.
Loop:
Find today's remaining time by subtracting today's end time minus the start time (the result should be a TimeSpan)
If today's remaining time is greater than the issue's remaining time, take today's date and today's starttime + issue remaining time
If the issue's remaining time is greater, set the issue's remaining time to be the issue's remaining time minus today's remaining time, move to tomorrow, and go to the top of the loop.
Using Stu's answer as a starting point, modify the IsInBusinessHours function to look up you business hours for the date parameter. A procedure like the following could be used:
CREATE PROCEDURE [dbo].[IsInBusinessHours]
#MyDate DateTime
AS
BEGIN
SELECT CASE Count(*) WHEN 0 THEN 0 ELSE 1 END AS IsBusinessHour
FROM WorkHours
WHERE (DATEPART(hour, StartHours) <= DATEPART(hour, #MyDate)) AND (DATEPART(hour, EndHours) > DATEPART(hour, #MyDate)) AND (Day = DATEPART(WEEKDAY,
#MyDate))
END

Categories

Resources