Sign in to follow this  
Followers 0
erik7426

Find the Last Tuesday of the Month

5 posts in this topic

I need to write a script to perform certain tasks on a server on certain days.

There are tasks to be done every Friday. (No Problem)

There are tasks to be done on the 1st and 15th of the month. (No Problem)

I have no problem checking today's date against those conditions.

Where I'm running into problems is checking today's date against specific days of the month.

Example:

How can I tell if today is the last Tuesday of the month? Last Thursday of the month? etc...

I found this script on the forum, but either I don't fully understand how to use it or it doesn't meet my needs.

#Region Func _OkToRun
    #cs ----------------------------------------------------------------------------
     AutoIt Version     :   3.2.10.0
     Author             :   Christophe Savard
     Script Function    :   Checks if today's the first Monday following the first Friday of the month"
     Parameters         :   $RundDay (Mandatory)    -   Weekday number (integer) when the script must run  (1 = Sunday to 7 = Saturday) 
                            $DayToTest (Optional)   -   Day number (interger) of the day to test
                                                        Possible values :
                                                        Null        ==> $RunDay value is considered as the target (same as schedule a basic weekly task)
                                                        An interger ==> Value must be higher than the $RunDay value (otherwise it's a basic weekly run)     
                            $Occurence (Optional)   -   Occurrence of the $DayToTest in the month (Default = 1)
                                                        Possible values :
                                                        Null        ==> default value is used (the first Occurrence = 1) if $DayToTest value is not empty
                                                        -1          ==> the last Occurrence of the $DayToTest value if existing
                                                                    ==> All Occurrences of $RunDay value if $DayToTest value is blank (it's a weekly run in fact)
                                                        -2          ==> the last occurence of the $DayToTest value
                                                        An integer  ==> the value will be used if it's in the range of date between day 1 and the $RunDay value.
                                                                        If the value is out of range sript stops and return an error message
                                                                        e.g : You try to test the 5th Friday of the month and the current month only contains 4 Fridays.
                            $Occurence (Optional)   -   Full path to a log file
                            
    Sample syntax       :   If you want the script to run the Monday following the first Friday of the month the syntax will be : $OK = _OkToRun (2,6,1) or _OkToRun (2,6)
                            If you want the script to run each Monday then the syntax will be : OK = _OkToRun (2)
                                    
     Return value       :   On success - 1  
                            On failure - 0 (and place a formated error message in a writelogfile)
     Requirement(s)     :   #include <Date.au3>
    #ce ----------------------------------------------------------------------------
    Func _OkToRun ($RunDay,$DayToTest,$Occurrence = 1, $LogFullPath="")
        If $LogFullPath then _FileWriteLog($LogFullPath,"===== START PROCESS " & _StringRepeat('=',80))
        Local $Retval = "", $Y, $M, $D
        #region Control of parameters validity and value
            If (Not IsInt ($RunDay) And $RunDay <> "") Or (IsInt ($RunDay) And ($RunDay > 7 Or $RunDay <= 0)) then $Retval = $Retval & "Parameter 1 cannot be " & '"' & $RunDay & '"' & ". It must be an Integer between 1 & 7." & @LF
            If $Runday= "" then $Retval = $Retval & "Parameter 1 is mandatory (a running day must be provided)." & @LF
            If (Not IsInt ($DayToTest) And $DayToTest <> "") Or  (IsInt ($DayToTest) And ($DayToTest > 7 Or $DayToTest <= 0) ) then $Retval = $Retval & "Parameter 2 cannot be " & '"' & $DayToTest & '"' & ". Possible values are : an Integer between 1 & 7 / Null value" & @LF
            If $DayToTest = $RunDay and $DayToTest <> "" then $Retval = $Retval & "Parameter 2 cannot be equal to parameter 1. the target day to test cannot be the running day !" & @LF
            If (Not IsInt ($Occurrence) And $Occurrence <> "") Or (IsInt ($Occurrence) And ($Occurrence = 0 Or $Occurrence > 4)) then $Retval = $Retval & "Parameter 3 cannot be " & '"' & $Occurrence & '"' & ". Possible values are : a number between 1 and 4 / [-1] for all Occurrences (weekly run) / [-2] for the last Occurrence / Null value" & @LF
            If $Occurrence = "" And $DayToTest <> "" then $Occurrence = 1; Set the default value for Occurence only if $DayToTest value is not empty...
            If $Occurrence = "" And $DayToTest = "" then $Occurrence = -1; otherwise set $Occurrence value to "all" (equivalent to a weekly run)
            If $Occurrence <> "" And $DayToTest = "" then $DayToTest = $RunDay; Weekly run but with an Occurrence condition (ex : 1st monday of the month)
            
            If $Retval then; Prepare retval for logfile update
                $SplitedRetval = StringSplit($Retval,@LF)
                For $i = 1 To $SplitedRetval[0]
                    If $LogFullPath then _FileWriteLog($LogFullPath,$SplitedRetval[$i])
                    If $i = $SplitedRetval[0]-1 then ExitLoop
                Next
                If FileExists($LogFullPath) then  _FileWriteLog($LogFullPath,"===== PROCESS ABORTED " &_StringRepeat('=',80))
                Return 0; Exit function if $Retval is not empty
            EndIf
            If @WDAY <> $RunDay then; Exit if today is not the Day number required by $Runday parameter
                If $LogFullPath then _FileWriteLog($LogFullPath, "Requested Run day is " & _DateDayOfWeek($RunDay,0) & " ==> Today is " & _DateDayOfWeek(@WDAY,0) & " !")
                If $LogFullPath then _FileWriteLog($LogFullPath,"===== PROCESS ABORTED " &_StringRepeat('=',80))
                Return 0
            ElseIf @WDAY = $RunDay then; Today's is the day...
                If $Occurrence = -1 then
                    If $LogFullPath then _FileWriteLog($LogFullPath,'Process run is granted !')
                    If $LogFullPath then _FileWriteLog($LogFullPath,"===== END PROCESS " &_StringRepeat('=',80))
                    Return 1; and $Occurrence = -1 this means it's a weekly run in fact
                EndIf
            EndIf
            
        #endregion Control of parameters validity and value
        
        #region Offset Calculation
        If $DayToTest <> $Runday then
            If $DayToTest > $Runday then
                $OffSet = $Runday + (7 - $DayToTest); Calculates the Offeset between $Runday and $DayToTest
            Else
                $OffSet = $Runday - $DayToTest
            EndIf
        EndIf
        #endregion Offset calculation
        
        #region $Occurrence consistancy test
        $ActualMthDayNbr = @MDAY; Gets the actual day number of the month
        
        Local $WeekDays[1] = [0] , $DayNum
        
        For $i=1 to $ActualMthDayNbr; loop to identify all the $Daytotest values in the month until today and gets the related dates
            $DayNum=_DateToDayOfWeek(@YEAR, @MON, $i)
            If $DayNum = $DayToTest then
                $WeekDays[0] += 1; adds 1 to the array counter
                ReDim $WeekDays[$WeekDays[0]+1]; Increase the boundary
                If StringLen($i) = 1 then
                    $WeekDays[$WeekDays[0]]= @YEAR & @MON & "0" & $i; Load the array element with the formated date.
                Else
                    $WeekDays[$WeekDays[0]]= @YEAR & @MON & $i; Load the array element with the formated date.
                EndIf
            EndIf
        Next

        If $Occurrence > $WeekDays[0] then
            If $LogFullPath then _FileWriteLog($LogFullPath,"Requested Occurrence is " & $Occurrence & " (parameter 3) " & "and the total available occurrences available up to now is " & $WeekDays[0] & "... ==> It's to early." &_StringRepeat('=',80))
            If $LogFullPath then _FileWriteLog($LogFullPath,"===== PROCESS ABORTED " &_StringRepeat('=',80))
            Return 0
        EndIf
        #endregion $Occurrence consistancy test
        
        If @Compiled=0 then _ArrayDisplay($WeekDays)
        
        #region Date checks
        If $Occurrence = -2 then
            $DateOfDaytoTest=$WeekDays[$WeekDays[0]]; Takes the last value in the array and therefore the target date just before the rundate.
        Else
            $DateOfDaytoTest=$WeekDays[$Occurrence]; Takes the value following $Occurrence parameter
        EndIf
        
        If @Compiled = 0 then MsgBox(0,"$DateOfDaytoTest",$DateOfDaytoTest)
        
        $JulianRunday = _DateToDayValue (@YEAR , @MON , @MDAY); Translate the $RundDay date into a julian date value
        _DayValueToDate ($JulianRunday - $Offset, $Y, $M, $D); Substracts the $Offset value to the $JulianRundDay value 
        If $Y & $M & $D = $DateOfDaytoTest then; compare the previous result with the result obtained just above
            If $LogFullPath then _FileWriteLog($LogFullPath,'Process run is granted !')
            If $LogFullPath then _FileWriteLog($LogFullPath,"===== END PROCESS " &_StringRepeat('=',80))
            Return 1; Dates are the same => Run can be done
        Else
            If $LogFullPath then _FileWriteLog($LogFullPath,"The target date is " &  $DateOfDaytoTest & " (Occurrence N° " & $Occurrence & " of the month)" & " and today's is to late !")
            If $LogFullPath then _FileWriteLog($LogFullPath,"===== PROCESS ABORTED " &_StringRepeat('=',80))
            Return 0
        EndIf
        #endregion Date checks
    EndFunc
#endregion Func _OkToRun

Any help would be greatly appreciated.

Share this post


Link to post
Share on other sites



Heres my go

#include <Date.au3>

$iDays = _DateDaysInMonth(@YEAR, @MON)

For $i = $iDays - 7 To $iDays
    $iWeekday = _DateToDayOfWeek(@YEAR, @MON, $i)

    If $iWeekday = 3 Then
        $LastTuesdayofmonth = $i
        ExitLoop
    EndIf
Next
MsgBox(4096, "", "Last tuesday of month is: " & $LastTuesdayofmonth)

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Share this post


Link to post
Share on other sites

Well, you can use JohnOne's solution if you are after getting ONE (last Tuesday, Friday ...) or, you can use this:

#include<date.au3>
#include<array.au3>

$DaysInMonth = _DateDaysInMonth(@YEAR, @MON)                        ;how many days the current month has
$LastDayInMonth = _DateToDayOfWeek(@YEAR, @MON, $DaysInMonth)       ;last day in the month (date format)

Dim $LastNamedDays[7][2]                                            ;array of [dates][last Weekday in month]

For $i = 0 To 6
    $LastNamedDays[$i][0] = @YEAR&"/"&@MON&"/"&_DateDaysInMonth(@YEAR, @MON)-$i
    If $LastDayInMonth - $i > 0 Then
        $LastNamedDays[$i][1] = "Last "&_DateDayOfWeek(Mod($LastDayInMonth-$i,7))
    Else
        $LastNamedDays[$i][1] = "Last "&_DateDayOfWeek(Mod($LastDayInMonth-$i,7)+7)
    EndIf
Next

_ArrayDisplay($LastNamedDays)

To get an array with Last "Weekdays" in current month.

The output is like this:

2011/06/30|Last Thursday

2011/06/29|Last Wednesday

You can easily match a date to a certain weekday - well, you will need to adapt the code to suit your needs. Pretty straightforward from here.

SNMP_UDF ... for SNMPv1 and v2c so far, GetBulk and a new example script

wannabe "Unbeatable" Tic-Tac-Toe

Paper-Scissor-Rock ... try to beat it anyway :)

Share this post


Link to post
Share on other sites

....

How can I tell if today is the last Tuesday of the month? Last Thursday of the month? etc...

....

Another interpretation of your problem.

#include<Date.au3>

Local $aNewDate = StringSplit(_DateAdd('d', 7, _NowCalcDate()), "/", 2) ; Add 7 days to today and split into an array.
Local $sToday = _DateDayOfWeek(_DateToDayOfWeek(@YEAR, @MON, @MDAY)); 

If $aNewDate[1] <> @MON Then ; If the month in 7 days does not equal today's month then
    MsgBox(4096, "", "Today is the last " & $sToday & " of this month.")
Else
    MsgBox(4096, "", "Today is not the last " & $sToday & " of this month.")
EndIf

Share this post


Link to post
Share on other sites

Thanks to everyone who replied. In the end I used Malkey's response because it needed the least amount of adjustment to fit into my existing script.

From his response I ended up with this function...

Func CheckDay()
    ;Function Returns Day of the Week. Range is 1 to 7 where 1=Sunday.
    Local $aNewDate = StringSplit(_DateAdd('d', 7, _NowCalcDate()), "/", 2) ; Add 7 days to today and split into an array.
    Local $sToday = _DateToDayOfWeek(@YEAR, @MON, @MDAY)

    If $aNewDate[1] <> @MON Then ; If the month in 7 days does not equal today's month then
        Return $sToday
    Else
        Return 0
    EndIf

EndFunc   ;==>CheckDay

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0