Count calendar days by Hrs/day - ignore certain days

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
AlleyArtwork
Posts: 44
Joined: 09 Jun 2015, 21:08

Count calendar days by Hrs/day - ignore certain days

05 Nov 2015, 16:37

Goal:
Subtract hours from a max hour amount, Count days on a calendar based on hours per day where there are hours consumed on a given day, while skipping over days where no hours are consumed, until all available hours from the original max hour amount are consumed.
What is the date when their hours exhaust?

Scenario 1:
120 hours vacation time
4x 10hr work schedule (for this example we'll say Mon-Thurs)
Input the schedule Mon:10hr, Tues:10hr, Wed:10hr, Thurs:10hr, Fri:0hr, Sat:0hr, Sun:0hr
Choose a start date on the calendar (example Nov 2 2015)
after submitting, the result is Nov 19 2015

Scenario 2:
120 hours vacation time
5x 8hr work schedule (for this example we'll say Sat-Wed)
Input the schedule Sat:8hr, Sun:8hr, Mon:8hr, Tues:8hr, Wed:8hr,
Choose a start date on the calendar (example Nov 7 2015)
after submitting, the result is Nov 25 2015

Math/script issues I need assistance with:
Originally I tried something with a simple GUI that took 3 values to get the number: exhaustdate := (((Vacay time / days per week) / hours per day) *7 ) -1
the -1 at the end is to make sure it counts back one day since the monthcal counts FROM the day instead of including the day.
Then from here i mark the selected date, then MyCalendar += %exhaustdate%,days then convert to longdate for an output.
This formula works great but ONLY if all 7 days of a week is worked. I need to figure out how to skip days of the week that someone has off.

I know that this person will have 12 days to use until the time is exhausted (120vacation hrs/10hr days = 12 days off) but how to convert skipped days into a number to keep counting beyond that day so that days with no hours used are passed over?
I figured that i'll need to make a more complex GUI to get the value for each day worked, that's the easy part.. but how to do it or make the values work as intended is where i'm stumped.
Any ideas?
Thanks all for looking!
User avatar
Exaskryz
Posts: 2882
Joined: 17 Oct 2015, 20:28

Re: Count calendar days by Hrs/day - ignore certain days

05 Nov 2015, 17:57

This is a demonstrative script. You will still need to figure out how to collect manually entered values to send into this script rather than the literally defined values I used.


Scenario 1:

Code: Select all

^7::
end:=20151102000000 ; this is a YYYYMMDDHH24MISS timestamp for Nov 2, 2015
Hours:={"aMon":10,"bTue":10,"cWed":10,"dThu":10,"eFri":0,"fSat":0,"gSun":0}
; the a, b, c, d, e, f, g prefixes are to make this array alphabetical. For loop automatically parses it alphabeitcally, not by the order they're in in the associative array. I'm sure there's some good reason for that.
; These otherwise match the output of the Day of the Week for the TimeStamp above
FormatTime, FirstDay, %end%, ddd
Vacay:=120
flag:=1 ; this is a trick for making sure it starts counting down on the first day and not monday
Loop
{
For day, time in Hours
   {
   If flag && (SubStr(day,2)!=FirstDay)
       Continue ; send the loop right back to the top of the For loop
   flag:=0 ; if it doesn't execute the continue line, then it'll turn flag off, so all other days of the week can get past the Continue
   Vacay-=time
   EnvAdd, end, 1, D
   If Vacay<0
          {
	  Vacay+=time ;	  re-add time to show the remainder of hours
          Break, 2 ; breaks out of the full loop
	  }
   else if Vacay=0
      Break, 2 ; there will be no remainder   
   }
}
EnvAdd, end, -1, D
FormatTime, lastDay, %end%, MMM dd yyyy
MsgBox %lastDay% with %Vacay% hours leftover.
return
Scenario 2:

Code: Select all

^7::
end:=20151107000000 ; this is a YYYYMMDDHH24MISS timestamp for Nov 7, 2015
Hours:={"aMon":8,"bTue":8,"cWed":8,"dThu":0,"eFri":0,"fSat":8,"gSun":8}
; the a, b, c, d, e, f, g prefixes are to make this array alphabetical. For loop automatically parses it alphabeitcally, not by the order they're in in the associative array. I'm sure there's some good reason for that.
; These otherwise match the output of the Day of the Week for the TimeStamp above
FormatTime, FirstDay, %end%, ddd
Vacay:=120
flag:=1 ; this is a trick for making sure it starts counting down on the first day and not monday
Loop
{
For day, time in Hours
   {
   If flag && (SubStr(day,2)!=FirstDay)
       Continue ; send the loop right back to the top of the For loop
   flag:=0 ; if it doesn't execute the continue line, then it'll turn flag off, so all other days of the week can get past the Continue
   Vacay-=time
   EnvAdd, end, 1, D
   If Vacay<0
          {
	  Vacay+=time ;	  re-add time to show the remainder of hours
          Break, 2 ; breaks out of the full loop
	  }
   else if Vacay=0
      Break, 2 ; there will be no remainder   
   }
}
EnvAdd, end, -1, D
FormatTime, lastDay, %end%, MMM dd yyyy
MsgBox %lastDay% with %Vacay% hours leftover.
return
All you really need to do is pass a timestamp to the variable end:= and make sure the array for Hours:={} is correctly filled out. You could set the numerical values to the name of a variable from a Gui (without the quotes; you don't want to make it a literal string) for example.

Feel free to ask any questions on this. This was a hackjob. I recognized value in an associated array, then tried to use a for-loop to access it. But then the for-loop would alphabetize each iteration. If I didn't put alphabetical prefixes on them, it would start with "Fri", then do "Mon", then "Sat"... ending on "Wed" and coming back to "Fri". So then when I need to make use of the first subtraction happening on the day that was specified at the beginning of the script (the end:= timestamp), I had to crop the alphabetical prefix off of it to compare with the FormatTime output. I utilized a flag variable in that too...

I mean, overall it works, but I have no doubt there would be somebody with a much more elegant script out there.
User avatar
AlleyArtwork
Posts: 44
Joined: 09 Jun 2015, 21:08

Re: Count calendar days by Hrs/day - ignore certain days

06 Nov 2015, 10:02

Thanks so much! The examples work great. and the ; comments are very much appreciated!
i'm having an issue getting the variables into the script from the gui. a msgbox shows me that it's just not taking the variables, or that I am not understanding how to use an array (more likely).

This is how I am testing it prior to using the GUI, but after inserting them into the array, it seems to break it unless I put the hard coded numbers back in.
The broken result is that %end% stays on the start date, which makes me believe i'm not using the array syntax correctly to include the variables.
i'm looking through the help files now as well to see if I see anything obvious

Code: Select all

hrmon = 10 ; Hours per day input box value
hrtue = 10 ; Hours per day input box value
hrwed = 10 ; Hours per day input box value
hrthur = 10 ; Hours per day input box value
hrfri = 0 ; Hours per day input box value
hrsat = 0 ; Hours per day input box value
hrsun = 0 ; Hours per day input box value

startdateselect = 20151102000000    ;  not using this yet.  will include this for the value for end eventually.
hravail = 120 ; total available hours input box value

end:=startdateselect  ; this is a YYYYMMDDHH24MISS timestamp for Nov 2, 2015
Hours:={"aMon":hrmon,"bTue":hrtue,"cWed":hrwed,"dThu":hrthur,"eFri":hrfri,"fSat":hrsat,"gSun":hrsun}
; the a, b, c, d, e, f, g prefixes are to make this array alphabetical. For loop automatically parses it alphabeitcally, not by the order they're in in the associative array. I'm sure there's some good reason for that.
; These otherwise match the output of the Day of the Week for the TimeStamp above
FormatTime, FirstDay, %end%, ddd
Vacay:=hravail
flag:=1 ; this is a trick for making sure it starts counting down on the first day and not monday
Loop
{
For day, time in Hours
   {
   If flag && (SubStr(day,2)!=FirstDay)
       Continue ; send the loop right back to the top of the For loop
   flag:=0 ; if it doesn't execute the continue line, then it'll turn flag off, so all other days of the week can get past the Continue
   Vacay-=time
   EnvAdd, end, 1, D
   If Vacay<0
          {
	  Vacay+=time ;	  re-add time to show the remainder of hours
          Break, 2 ; breaks out of the full loop
	  }
   else if Vacay=0
      Break, 2 ; there will be no remainder   
   }
}
EnvAdd, end, -1, D
FormatTime, lastDay, %end%, MMM dd yyyy
MsgBox %lastDay% with %Vacay% hours leftover.
return
Last edited by AlleyArtwork on 06 Nov 2015, 10:53, edited 1 time in total.
User avatar
Exaskryz
Posts: 2882
Joined: 17 Oct 2015, 20:28

Re: Count calendar days by Hrs/day - ignore certain days

06 Nov 2015, 10:05

I haven't run your code, but remove the %'s in your Hours:={} array. Such as "aMon":hrmon,"bTue":hrtue. That should hopefully fix it.
User avatar
AlleyArtwork
Posts: 44
Joined: 09 Jun 2015, 21:08

Re: Count calendar days by Hrs/day - ignore certain days

06 Nov 2015, 10:35

This worked! Thanks :)
Also, i had to remove the % around the hours available variable.
presumably i'll need to do the same for the start date variable as well once I introduce that.
I'll edit my example above to the working one in case anyone else finds it useful. Thanks again!
User avatar
AlleyArtwork
Posts: 44
Joined: 09 Jun 2015, 21:08

Re: Count calendar days by Hrs/day - ignore certain days

10 Nov 2015, 21:33

Many thanks Exaskryz!
I posted some pictures of the app I made using your help with the calculations.
This tab originally only housed a "Date Wheel" (digital version of these paper/cardboard date wheels with several layers that you adjust to figure stuff out with like: "20 weeks from now is which day"... or "96 days from now is which day").
Now it is 2 halves. Top and Bottom (and maybe a tad crowded) but both functions use the calendar so it made sense to keep it there.

The LOWER half is where I used your code (modified for the app). I recycled the use of the Calendar and some of the other fields from the Date Wheel to be used in the Time Exhauster.
This is the application prior to filling anything out.
Image

This is the application after selecting a start date on the calendar, filling out hours, and clicking exhaust.
All of the text box controls can be used as variables within other portions of the application which hosts custom hotkeys that users can build build responses based on results from the calculations to include the data within the response :) (I thought it was nifty anyway).
Image

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: ht55cd3 and 254 guests