Output dates based on an array - scheduled-tasks

Need Help. I have an associative array which has the days of the week. I know very little about arrays. Each day has a 1 or 0 in the array below. I am trying to output dates and use them to generate tasks. I'm sure can this be done easily, but I lack the experience.
I want to output only dates which have 1's as shown in the array below.
The first task is due in 4 days.
I need to view dates up to 3 days ahead, so if today is Tuesday, and start is on Friday, then the Friday task date won't appear until Wednesday.
Today := A_now
WeekDays_Array := {Sun: 0, Mon: 0, Tue: 1, Wed: 0, Thu: 1, Fri: 1, Sat: 0}

I am pretty sure this is most of it. The suggestion to use the array above made the most sense.
The script uses Wkday (which is A_Now) as the start day but I think that can be changed by substituting it for a specific start day
PastDue := []
DueBy := []
;~ Weekday_Array := {Sunday: 0, Monday: 0, Tuesday: 1, Wednesday: 0, Thursday: 1, Friday: 1, Saturday: 0}
Weekday_Array := [1,1,1,1,1,1,1] ;Represents Sun-Saturday
AssignTask:
FormatTime, WkDay, MyTime, WDay
For i, value in Weekday_Array{
DueDate =
if (i > WkDay && Value = 1){
x++
DueDate += (x), days
FormatTime, DueDate, % DueDate, MM/dd/yy
DueBy.InsertAt(i,DueDate)
}
if (i = WkDay && Value = 1){
FormatTime, DueDate, % A_Now, MM/dd/yy
DueBy.InsertAt(i,DueDate)
}
if (i < WkDay && Value = 1){
y--
Pastdate =
PastDate += (y) , days
NewDate := PastDate
NewDate += 7, days
FormatTime, PastDate, % PastDate, MM/dd/yy
FormatTime, NewDate, % NewDate, MM/dd/yy
PastDue.InsertAt(i,PastDate)
DueBy.insertAt(i,NewDate)
}
}
For i, PastDue in PastDue
PastDueDates .= PastDue "`n"
Sort, PastDueDates
PastDueDates := "Past due dates so far this week `n`n" PastDueDates
MsgBox, 0x1000,, % PastDueDates
For i, DueDate in DueBy
DueDates .= DueDate "`n"
Sort, DueDates
DueDates := "All upcoming due dates based criteria `n`n" DueDates
MsgBox, 0x1000,, % DueDates
sort, DueDates
FormatTime, xDay1, % A_Now, MM/dd/yy
xDay2 += 1, days
FormatTime, xDay2, % xDay2, MM/dd/yy
xDay3 += 2, days
FormatTime, xDay3, % xDay3, MM/dd/yy
For i, DueDate in DueBy{
if (DueDate = xDay1 || DueDate = xDay2 || DueDate = xDay3)
XDays .= DueDate "`n"
}
xDays := "Only view the next 3 days from today `n`n" xDays
MsgBox, 0x1000,, % xDays
;~ return
*esc::
ExitApp
return

Related

How to select a date in a sysmonth Control in autohotkey

i'm trying to select a date in a monthcal with the sendmessage cmd from AHK. Unfortunately, this is not working and i don't know where is my mistake or my misunderstanding. Anyone could help ? Here's what i already try.
ConvertNormalDateToSystemTime(YYYYMMDD)
; this return a SystemTime format date from a normal date
{
YYYYMMDD.=000000
YYYYMMDDHHMISS:=YYYYMMDD
VarSetCapacity(SystemTime, 16, 0) ; This struct consists of 8 UShorts (i.e. 8*2=16).
Int := SubStr(YYYYMMDDHHMISS, 1, 4) ; YYYY (year)
NumPut(Int, SystemTime, 0, "UShort")
Int := SubStr(YYYYMMDDHHMISS, 5, 2) ; MM (month of year, 1-12)
NumPut(Int, SystemTime, 2, "UShort")
Int := SubStr(YYYYMMDDHHMISS, 7, 2) ; DD (day of month)
NumPut(Int, SystemTime, 6, "UShort")
Int := SubStr(YYYYMMDDHHMISS, 9, 2) ; HH (hour in 24-hour time)
NumPut(Int, SystemTime, 8, "UShort")
Int := SubStr(YYYYMMDDHHMISS, 11, 2) ; MI (minute)
NumPut(Int, SystemTime, 10, "UShort")
Int := SubStr(YYYYMMDDHHMISS, 13, 2) ; SS (second)
NumPut(Int, SystemTime, 12, "UShort")
return % &SystemTime
}
MCM_FIRST:= 0x1000
MCM_SETCURSEL:= MCM_FIRST + 2
MyDate:= 20211115
WinActivate ahk_class AutoHotkeyGUI, ExempleCalendrier.ahk
dateASelectionnerDansCalendrier := ConvertNormalDateToSystemTime(20211115)
try
{
SendMessage MCM_SETCURSEL , , &dateASelectionnerDansCalendrier, SysMonthCal321, ahk_class AutoHotkeyGUI ; THIRD TRIAL
MsgBox % ErrorLevel
}
catch e
{
MsgBox % ErrorLevel
}
An other strange thing is that i always get the MCM_SETCURSEL message back in MyReturn variable. I already try to compile the script and run it as admin. I know that there is no multiselected option on my monthcal. Someone on Discord suggest me that MCM_SETCURSEL lparam was pointing to a systemtime. So how could i send my date to my monthcal ? Should i convert my actual date into a systemTime in an other way ? (speaking as a noob)
Thanks for any help !

Add to date or time in AutoHotkey

I was looking for an inbuild ahk function that allows the user to add days, months, years or even time to an existing day thus converting it correctly to a new month if the day count reaches 32. I didn't find anything, so I came up with this little solution:
; returns an array [year, month, day, hour, minute, second]
DateTimeAdd(v_a_now,yearPlus=0,monthPlus=0,dayPlus=0,hrPlus=0,minPlus=0,secPlus=0) {
daysInMonth := { 1:31, 2:28, 3:31, 4:30, 5:31, 6:30, 7:31, 8:31, 9:30, 10:31, 11:30, 12:31 }
; Parse data from an A_NOW type format
; If you pass your custom "A_NOW" format remember that numbers < 10 are expected to have a leading 0
day := SubStr(v_a_now,7,2) + dayPlus
month := SubStr(v_a_now,5,2) + monthPlus
year := SubStr(v_a_now,1,4) + yearPlus
hours := SubStr(v_a_now,9,2) + hrPlus
minutes := SubStr(v_a_now,11,2) + minPlus
seconds := SubStr(v_a_now,13,2) + secPlus
; Start formatting
if(seconds >= 60) {
tadd := seconds / 60
seconds -= Floor(tadd) * 60
minutes += Floor(tadd)
}
if(minutes >= 60) {
tadd := minutes / 60
minutes -= Floor(tadd) * 60
hours += Floor(tadd)
}
if(hours >= 24) {
tadd := hours / 24
hours -= Floor(tadd) * 24
day += Floor(tadd)
}
; We have to format the month first in order to be able to format the days later on
if(month >= 13) {
tadd := month / 12
month -= Floor(tadd) * 12
year += Floor(tadd)
}
; Assmuning the number of days is an absurd number like 23424 we need to go through each month and subtract the max. amount of days from that month
cond := true
while(cond) {
; Get the number of max. days in this current month (sadly no loop years included :< )
max_days_in_this_month := daysInMonth[month]
; If the number of days i.e. 42 is great than 31 for example in January
if(day > max_days_in_this_month) {
; Subtract max. allowed days in month from day
day -= max_days_in_this_month
; New Year?
if(month == 12) {
month := 1
year++
} else {
month++
}
} else {
cond := false
}
}
; Add leading zero to numbers
return_array := [year, month, day, hours, minutes, seconds]
i := 2
while(i != return_array.MaxIndex()+1) {
thisIteration := return_array[i]
if(thisIteration <= 9) {
return_array[i] := "0" thisIteration
}
i++
}
; Done formatting
; For testing
;~ msg := return_array[1] "/" return_array[2] "/" return_array[3] " " return_array[4] ":" return_array[5] ":" return_array[6]
;~ msgbox % msg
return return_array
}
Sadly this function does not take loop years into aspect. Do you guys know any better alternatives?
Check out EnvAdd at https://autohotkey.com/docs/commands/EnvAdd.htm
EnvAdd, Var, Value, TimeUnits
equivalent to
Var += Value, TimeUnits
EnvAdd sets a date variable Var (in YYYYMMDDHH24MISS format) to the sum of itself plus the given date value Value using the timeunits parameter.
Example:
newDate := %A_Now% ; or whatever your starting date is
EnvAdd, newDate, 20, days
NewDate += 11, days
MsgBox, %newDate% ; The answer will be the date 31 days from now.

Convert string month to numeric

I have a variable period that contains a month as an abbreviated string (i.e. "JAN", "FEB", "MAR", etc). How do I convert period to a numeral (i.e. 1, 2, 3, etc)?
My solution is:
gen fake_date_s = "2000"+period+"1"
gen fake_date = date(fake_date_s, "YMD")
gen month = month(fake_date)
I don't think it's ugly:
clear
input ///
str3 period
JAN
FEB
DEC
end
list
gen monthnum = month(date("2000" + period + "1", "YMD"))
list
This also works:
gen monthnum = month(date(period, "M"))
as it sets the day and the year in the daily date to 01 and 1960, by default.
I'm sure you can find an alternative that doesn't use date functions, but why not use them?
Another approach is:
local i=1
foreach m in `c(Mons)' {
replace month = "`i'" if month == upper("`m'")
local ++i
}
destring month, replace

Get today -2 (skipping weekend)

How can I get the Today -2 days (the last 2 working days from now)? but skipping the weekend?
Example #1: Today is February 25, I want February 21
Example #2: Today is February 26, I want February 24
PS: Date format is DD/MM/YYYY
I have this, but the result is going forward, should I use datediff or what?:
<%
Dim d
d = DateAdd("m", 1, Now)
d = "01/" & Month(d) & "/" & Year(d)
d = DateAdd("d", -1, d)
If Weekday(d) = 7 Then
d = DateAdd("d", -1, d)
ElseIf Weekday(d) = 1 Then
d = DateAdd("d", -2, d)
End If
Response.Write "Day: " & d
%>
To get your desired result you need to subtract 3 days on Saturdays, 4 days on Sundays and Mondays, and 2 days on all other days. This can be achieved with something like this:
today = Now
num = Weekday(today, vbWednesday)
d = today - (2 + num\5 + num\6)
response.write "Two working days back: " & d
The Weekday function returns a numeric value for each weekday. By basing the week on Wednesday you can calculate the additional number of days you need to subtract from the current date with integer divisions:
num\5 returns 1 for Saturday, Sunday and Monday, and 0 otherwise.
num\6 returns 1 for Sunday and Monday, and 0 otherwise.
Thus the term 2 + num\5 + num\6 becomes 3 for Saturdays, 4 for Sundays and Mondays, and 2 for all other days.
This might be overkill for what you need but here are two routines I use in my scripts to add or subtract workdays while considering weekends and holidays.
Function AddWorkingDays(dtStart, intDays)
' Start/Default case...
AddWorkingDays = CDate(dtStart)
' If positive days, step forward, otherwise step backward...
Dim intStep, intCount
If intDays > 0 Then intStep = 1 Else intStep = -1
Do While intCount <> intDays
AddWorkingDays = AddWorkingDays + intStep
If IsValidDate(AddWorkingDays) Then intCount = intCount + intStep
Loop
End Function
Function IsValidDate(d)
Dim intWeekday, intMonth, intDay
intWeekday = Weekday(d)
intMonth = Month(d)
intDay = Day(d)
' Weekend dates are not acceptable...
If intWeekday = vbSaturday Or intWeekday = vbSunday Then Exit Function
' Holidays are also not acceptable...
If intMonth = 01 Then If intDay = 01 Then Exit Function ' New Year's Day
If intMonth = 07 Then If intDay = 04 Then Exit Function ' Independence Day
If intMonth = 12 Then If intDay = 25 Then Exit Function ' Christmas Day
' Memorial Day is the last Monday in May...
If intWeekday = vbMonday Then If intMonth = 05 Then If intDay >= 25 Then Exit Function
' ... (Thanksgiving, others) ...
' All tests passed. Date is a valid workday...
IsValidDate = True
End Function

Which days are work days in a given date range

Is there a built in function that will tell me which days are work days? this is what i mean,
If I were to choose today's date (6/14/2011), it will give me any inspection numbers clocked out today. This lead time includes weekends. So if I had a customer start a project on the 10th (Friday) and finish it today; it would show it took about five days, instead of three.
I believe there used to be a function to do this a long long time ago, but I believe that function has since been removed. I believe that you should be able to use something like the following which calculates the business days between two dates:
DateDiff ("d", {Orders.OrderDate}, {Orders.ShipDate}) -
DateDiff ("ww", {Orders.OrderDate}, {Orders.ShipDate}, crSaturday) -
DateDiff ("ww", {Orders.OrderDate}, {Orders.ShipDate}, crSunday)
This gets the total days difference and subtracts the saturdays and sundays from the total. Note this does not include holidays. For that you'd need to maintain them in your own User Function Library and include them in the calculation.
Hope this helps.
This is the solution i came up with. Pretty much if it is anything over 7 days i know how many days to subtract. if it is under 7 days i can still figure out if it spanned the weekend. Crystal reports has a function DayOfWeek that returns a number for the day i.e. Sunday = 1, Monday = 2, etc. If the finish time day number is less than the start time number we know it passed the weekend. and we can subtract 2.
timeDiff is startdate - finishdate.
if({#timeDiff} >= 35) then
{#timeDiff} - 10
else if({#timeDiff} >= 28) then
{#timeDiff} - 8
else if({#timeDiff} >= 21) then
{#timeDiff} - 6
else if({#timeDiff} >= 14) then
{#timeDiff} - 4
else if({#timeDiff} >= 7) then
{#timeDiff} - 2
else if(DayOfWeek({Command.Finishdate}) < DayOfWeek({Command.Startdate})) then
{#timeDiff} - 2
else
{#timeDiff}
I have a more in depth explanation on my website. the link is here
Here is a monster solution that also takes public holidays into account:
// WorkingDays
// Count the number of working days between a start and an end date.
//
// startDate - first date in the interval
// endDate - last date in the interval
// countStartAndEnd - if true 1 feb to 2 feb will count as 2 days
// if false 1 feb to 2 feb will count as 1 day
// given both of them are working days
Function (dateVar startDate, dateVar endDate, optional booleanVar countStartAndEnd := False)
local NumberVar Weeks;
local NumberVar Days;
local NumberVar Hol;
// 5 days for every week (whole or partial)
Weeks := (Truncate (endDate - dayofWeek(endDate) + 1 - (startDate - dayofWeek (startDate) + 1)) /7 ) * 5;
// Number of days in partial weeks (can be positive or negative)
Days := DayOfWeek(endDate) - DayOfWeek(startDate) + 1 +
(if DayOfWeek(startDate) = crSunday then -1 else 0) +
(if DayOfWeek(endDate) = crSaturday then -1 else 0);
// Count number of public holidays in the period
local NumberVar iYear;
local NumberVar i;
for iYear := Year(startDate) to Year(endDate) do (
Local DateVar Array Holidays := getHolidays(iYear);
for i := 1 to uBound(Holidays) do (
local NumberVar hMonth := Month(Holidays[i]);
local NumberVar hDay := Day(Holidays[i]);
local DateVar hDate := cDate(iYear, hMonth, hDay);
if DayOfWeek(hDate) in crMonday to crFriday and
hDate in startDate to endDate then Hol := Hol+1;
);
);
// Return number of working days
Weeks + Days - Hol - toNumber(not countStartAndEnd);
Code above modified from solution found at KenHamady.
The following function is called by the previous function and returns all public holidays:
// getHolidays
// Returns an array with all public holidays for a given year
// These are Swedish holidays. Modify as needed.
Function (Numbervar yyyy)
Datevar Array holidays;
local Datevar holiday;
local Datevar easterSunday := getEasterSunday(yyyy);
// New Years Day
// 1 jan
holiday:=Date(yyyy, 1, 1);
Redim Preserve holidays[Ubound(holidays)+1];
holidays[Ubound(holidays)]:=holiday;
// Epiphany
// 6 jan
holiday:=Date(yyyy, 1, 6);
Redim Preserve holidays[Ubound(holidays)+1];
holidays[Ubound(holidays)]:=holiday;
// Good Friday
// 2 days before easter sunday
holiday:=cDate(DateAdd("d", -2, easterSunday));
Redim Preserve holidays[Ubound(holidays)+1];
holidays[Ubound(holidays)]:=holiday;
// Holy Saturday
// 1 day before easter sunday
holiday:=cDate(DateAdd("d", -1, easterSunday));
Redim Preserve holidays[Ubound(holidays)+1];
holidays[Ubound(holidays)]:=holiday;
// Easter Sunday
// The first Sunday following the first ecclesiastical full moon that occurs on or after the day of the vernal equinox
holiday:=cDate(DateAdd("d", -2, easterSunday));
Redim Preserve holidays[Ubound(holidays)+1];
holidays[Ubound(holidays)]:=holiday;
// Easter Monday
// 1 day after easter sunday
holiday:=cDate(DateAdd("d", 1, easterSunday));
Redim Preserve holidays[Ubound(holidays)+1];
holidays[Ubound(holidays)]:=holiday;
// Labour day
// 1 may
holiday:=Date(yyyy, 5, 1);
Redim Preserve holidays[Ubound(holidays)+1];
holidays[Ubound(holidays)]:=holiday;
// Ascension
// 39 days after easter sunday
holiday:=cDate(DateAdd("d", 39, easterSunday));
Redim Preserve holidays[Ubound(holidays)+1];
holidays[Ubound(holidays)]:=holiday;
// National day
// 6 june
holiday:=Date(yyyy, 6, 6);
Redim Preserve holidays[Ubound(holidays)+1];
holidays[Ubound(holidays)]:=holiday;
// Midsummer's eve
// The friday in the interval 19 june - 25 june
holiday:=cDate(DateAdd("d", 1-dayOfWeek(Date(yyyy, 6, 25), crFriday), Date(yyyy, 6, 25)));
Redim Preserve holidays[Ubound(holidays)+1];
holidays[Ubound(holidays)]:=holiday;
// All saints' day
// The saturday in the interval 31 october - 6 november
holiday:=cDate(DateAdd("d", 1-dayOfWeek(Date(yyyy, 11, 6), crSaturday), Date(yyyy, 11, 6)));
Redim Preserve holidays[Ubound(holidays)+1];
holidays[Ubound(holidays)]:=holiday;
// Christmas eve
// 24 december
holiday:=Date(yyyy, 12, 24);
Redim Preserve holidays[Ubound(holidays)+1];
holidays[Ubound(holidays)]:=holiday;
// Chritmas day
// 25 december
holiday:=Date(yyyy, 12, 25);
Redim Preserve holidays[Ubound(holidays)+1];
holidays[Ubound(holidays)]:=holiday;
// St. Stephen's Day
// 26 december
holiday:=Date(yyyy, 12, 26);
Redim Preserve holidays[Ubound(holidays)+1];
holidays[Ubound(holidays)]:=holiday;
// New year's eve
// 31 december
holiday:=Date(yyyy, 12, 31);
Redim Preserve holidays[Ubound(holidays)+1];
holidays[Ubound(holidays)]:=holiday;
holidays;
Code above based on the custom function in this post by craig.
The holiday function need to be able to get the date for easter sunday for a given year:
// getEasterSunday
// Returnes a dateVar of the easter sunday for a given year
//
// Based upon formula from http://aa.usno.navy.mil/faq/docs/easter.php
Function (numberVar yyyy)
local numberVar c := int(yyyy / 100);
local numberVar n := yyyy - 19 * int(yyyy / 19);
local numberVar k := int((c-17)/25);
local numberVar i := c - int(c/4) - int((c-k)/3) + 19*n + 15;
i := i - 30 * int(i/30);
i := i - int(i/28) * ( 1 - int(i/28) * int(29/(i+1)) * int((21-n)/11));
local numberVar j := yyyy + int(yyyy/4) + i + 2 - c + int(c/4);
j := j - 7 * int(j/7);
local numberVar l := i - j;
local numberVar m := 3 + int((l+40)/44);
local numberVar d := l + 28 - 31 * int(m/4);
cDate(yyyy, m , d);
Easter sunday calculation formula from United States Naval Observatory.