How do you define the first day of the month (without including week-ends) in a batch script?

I have created a scheduled task in Windows that consists of running a batch script. The problem is that this task has to be scheduled every 1st day of the month except for weekends.

For example, for the month of May, this task should run on May 02nd.

As I can't do it via the task scheduler, my idea is to schedule the execution task every day and add a condition checking that the execution day is the 1st day of the month excluding weekends.

This script would be of the following form :

if %date% = firstday
C:/MyExec/popo.exe arg1 arg2

Can you help me to write this script please?

Thank you in advance.

2 answers

  • answered 2022-05-04 11:44 Gerhard

    There are loads of standard methods already created for this, so just for me to experiment a bit, here is an untested method (untested meaning I simply ensured there are no syntax errors, but I have not tested all dates scenarios etc:

    @echo off
    if not exist _mlock break>_mlock
    for /f "tokens=1-3*delims=_" %%i in ('PowerShell -Command "& {Get-Date -format "dd_ddd_MM"}"') do (
        if %%i lss 5 if /i not "%%j" == "Sat" if /i not "%%j" == "Sun" findstr "m%%k">nul _mlock || (
            echo m%%k>"_mlock"
            start "" "C:\MyExec\popo.exe" "arg1" "arg2"
        )
    )
    

    The concept: Use powershell to get a non-locale dependent dd ddd mm (04 Wed 05). I check for the day number, if it is less than 5 (overkill in this scenario) and if the ddd is not Sat or Sun and if the month's lock file does not contain the current month number, it will launch the command. If however the lock file contains the month, it will skip it until the month is updated in the file.

    You're welcome to test this, if you are not happy with the temp holding file method, you can also let it add the month as a lock to the batch-file itself instead.

    Notes:

    1. This does not cater for public holidays, only weekends as per your request.
    2. The ddd day result is language dependent and will require you to amend Sat and Sun accordingly on non English Operating systems.

  • answered 2022-05-04 13:19 Wisblade

    This version is language-independent, excepted for optional display, and doesn't require lock files.

    I've put comments inside the batch itself, feel free to ask for precisions if needed. I've tested it for March and May 2022, it works and doesn't trigger the command more than one time per month.

    @echo off
    setlocal enableextensions enabledelayedexpansion
    
    REM Get current date. Powershell is used to get values in a fixed order.
    for /f "usebackq tokens=1-3 delims=/" %%A in (`PowerShell -Command "& {Get-Date -format "dd/MM/yyyy"}"`) do (
        set DD=%%A
        set MM=%%B
        set YY=%%C
        REM Scheduled day.
        set EDD=01
    )
    REM Not during first 3 days? Skip.
    if !DD! GTR 3 (
        echo !DD!/!MM!/!YY!: Not first days of month, no need to test.
        goto :eof
    )
    REM Compute day of week: 0=Monday, ... 5=Saturday, 6=Sunday.
    set /A c=(14-!MM!)/12
    set /A y=!YY!-!c!
    set /A m=!MM!+(12*!c!)-2
    set /A d=((!EDD!-1+!y!+(!y!/4)-(!y!/100)+(!y!/400)+((31*!m!)/12))) %% 7
    REM Get human-readable day. Change according to your own language, if needed. Keep order, of course.
    set DAYS=Monday Tuesday Wednesday Thursday Friday Saturday Sunday
    set /A i=0
    for %%A in (!DAYS!) do (
       set DAY=%%A
       if !i! EQU !d! goto :found_day
       set /A i+=1
    )
    :found_day
    echo Day of week for !EDD!/!MM!/!YY!: !d! ^(!DAY!^)
    REM If EDD is during week-end, increase expected day (2 days for Saturday, 1 day for Sunday)..
    if !d! GEQ 6 (
        set /A EDD+=7-!d!
        REM Handle non-significative zero.
        if !EDD! LSS 10 (
            set EDD=0!EDD!
        )
        echo On week-end, schedule it to !EDD!/!MM!/!YY! instead.
    )
    REM Are we on scheduled day EXACTLY?
    if !DD! EQU !EDD! (
        REM Executing command now.
        echo Executing: C:\MyExec\popo.exe arg1 arg2
        REM C:\MyExec\popo.exe arg1 arg2
        goto :eof
    )
    REM We're before or after schedule, but stil within the first three days in the month.
    echo Unscheduled for today ^(!DD!/!MM!/!YY!^).
    goto :eof
    

    The "day of week" formula comes from here: Mathematical curiosities / Find the day of the week with a given date (in French).

    I took also Gerhard's trick for obtaining a fixed date format quickly through Powershell. It could also have been done with an embedded VBS script, since this language natively have the Weekday function, but it may have been quite unreadable to add a temporary script generation within the batch itself.

How many English words
do you know?
Test your English vocabulary size, and measure
how many words do you know
Online Test
Powered by Examplum