# Date calculation algorithm

I'm working on a project to schedule a machine shop, basically I've got everything covered BUT date calculations, I've got a method called schedule (working on PHP here):

``````public function schedule(\$start_date, \$duration_in_minutes)
``````

Now my problem is, currently I'm calculating end time manually because time calculations have the following rules:

1. During weekdays, work with business hours (7:00 AM to 5:00 PM)
2. Work on Saturdays from 7:00 AM to 2:00 PM
3. Ignore holidays (in Colombia we have A LOT of holidays)

I already have a lookup table for holidays, I also have a Java version of this algorithm that I wrote for a previous version of the project, but that one's also manual.

Is there any way to calculate an end time from a start time given duration?, my problem is that I have to consider the above rules, I'm looking for a (maybe?) math based solution, however I currently don't have the mind to devise such a solution myself.

I'll be happy to provide code samples if necessary.

-
What do you mean by "manual"? To me, that means that the user calculates the end date himself, but I think you just mean that your code adds up the available days one at a time until it has accounted for the appropriate number of hours. If so, what's wrong with that? – Caleb Dec 11 '12 at 17:16
There is no way to make "math based solution" because holiday distribution in a given year is random. You have to make a loop which will check for the each day whether it is a holiday, a weekday or a weekend and then add appropriate amount of minutes and check if you've achieved \$duration_in_minutes – onlineapplab.com Dec 11 '12 at 17:21
Both of your comments are true: @Caleb I do count one at a time, the thing is that each operations usually takes less than a day, the holes on my algorithm are things such as what happens when there's a month change or other fringe cases. – Julian Cuevas Dec 11 '12 at 22:31
@onlineapplab.com I know that math based solutions for holiday checking is difficult (actually in Colombia, holidays are defined by a set of rules, so they're not random). My issue is that my code adds hours and minutes one at a time which is error-prone and slow. – Julian Cuevas Dec 11 '12 at 22:38
@JulianCuevas Divide each day into chunks eg 3h - 30m lunch break - 5h then add those chunks. I think that your question requires some clarification eg \$duration_in_minutes represents shift time (so it is time per day) or it can be something like 120h and you want to calculate how many days it will take to finish aloted time. – onlineapplab.com Dec 12 '12 at 10:08

It's a C# implementation of everything in your algorithm except for holidays (which you should be able to figure out given the rest of the code).

You start off by modeling a working week (Monday-Friday, 8am-5pm, for example, with an hour a day for lunch). Then you can ask it questions like "if I have a task that takes 15 hours and I start at 9:22 on Tuesday, when will I finish?"

If you've done some Java before hopefully you'll be able to read the C#. Alternatively, there's a JavaScript port here:

-
This is exactly what I was looking for, actually I think I can take the javascript and make it work client side, maybe that way the server will only handle CRUD operations, thank you very much!! – Julian Cuevas Dec 11 '12 at 22:55

Sounds like a table to list holidays, and check the date against that table, then check the day of week for that date (\$dw = date( "w", \$timestamp);).. Have a table for the hours for each day of the week (this makes this configurable). Then subtract out hours from the start date until you have no more hours to subtract out..

pseudocode:

``````while \$durationhours > 0
{
\$hoursinday = \$hours["dayoftheweek"];
if( \$hoursinday > \$durationhours )
{
\$endtime = \$durationhours+\$day["starttime"];
}
else
{
\$durationhours = \$durationhours = \$hoursinday;
}
}
``````

Does that work?

-
It's a little simplistic - you'd want to use a table of start times with durations stored against each day of the week in order to allow for lunch breaks, etc. (So: Monday: 9am, 4 hours; 2pm, 3 hours). Otherwise you'll end up being an hour off. You'd probably also need a more optimal algorithm for calculating end time: figure out the duration of a week, then divide the duration by that amount of time in order to figure out how many weeks are represented. Subtract that time. Then do the same for days. Otherwise, long durations can result in long calculations. – Ant Dec 11 '12 at 17:55
The solution works, I also don't need to take lunch into account due to the fact that the machines keep on working and there's 3 lunch shifts, so no machine is ever unattended. However short calculations are a priority – Julian Cuevas Dec 11 '12 at 22:54

What you can do is as below:

Keep the timezone of Columbia as default when you are using this function.

1. take an array of dates which having holiday and skip those dates all hours in using this.
2. check whether it is Saturday, than keep only limited hours you want.
3. for all other days keep working hours in calculations.
a) for weekdays/Saturday you will have to check for timings like 7am to 5pm and 7am to 2pm and with conditions and looping of each minutes increment and also condition to check about duration. That's it.

Its bit told simply but without code, this is enough.

-