Can cron do this?

Edit: This is version 2.0. One thing version 1.0 could not handle is running something every other week. This version handles that and it now requires my datecalc script. You may need to adjust the alias if you install datecalc somewhere other than /usr/local/bin.

To understand to even/odd stuff: datecalc -j can return a day number for a given month day and year. And datecalc -d can return a numeric day-of-week. Subtract the second from the first and you get the day number of the sunday that starts the week. Divide that by 7 and you get a week number. Now we just need to test that for even or odd.

And now the code...

#! /usr/bin/ksh
alias datecalc=/usr/local/bin/datecalc

#  weekselector ---  script to assist in scheduling cron jobs
#  Perderabo  Oct 11, 2003
#
#  example:
#  You want to run command1 on the first monday of each month and
#  you want to run command2 on the last monday of each month.
#  Just use this syntax:
#
#    0 0 * * 1 /usr/local/bin/weekselector 1st && command1
#    0 0 * * 1 /usr/local/bin/weekselector last && command2
#
#  Version 2.0  March 23, 2005
#
#  You can now use "even" or "odd" to run commands every other week.
#  Whether or not a week is "even" or "odd" is arbitrary, but if one week
#  is "odd", the next will be "even".  An "even" Monday will be in the same
#  week as an "even" Tuesday.

integer month day year first last leap

set -A mdy $(date "+%m %d %Y")
month=${mdy[0]}
day=${mdy[1]}
year=${mdy[2]}
#date "+%M %d %Y"  | read month day year

case $1 in
    even|Even|EVEN|odd|Odd|ODD)
            integer dow mjd fmjd wk
            dow=$(datecalc -d $year $month $day)
            mjd=$(datecalc -j $year $month $day)
            ((fmjd=mjd-dow))
            ((wk=fmjd/7))
            ((wk=wk+${#1}))
            ((wk/2*2 == wk))
            exit $?
            ;;
    1|1st|1ST|first|First|FIRST)    last=7  ;;
    2|2nd|2ND|second|Second|SECOND) last=14 ;;
    3|3rd|3RD|third|Third|THIRD)    last=21 ;;
    4|4th|4TH|fourth|Fourth|FOURTH) last=28 ;;
    last|Last|LAST)
            #                 ja fe ma ap ma jn jl ag se oc no de
            set -A mlength xx 31 28 31 30 31 30 31 31 30 31 30 31

            if ((month != 2)) ; then
                last=${mlength[month]}
            else
                leap=0
                if ((!(year%100))); then
                        ((!(year%400))) && leap=1
                else
                        ((!(year%4))) && leap=1
                fi

                last=28
                ((leap)) && last=29
            fi;;
    *) exit 1;;
esac
((first=last-6))

((first<=day && day<=last))
exit $?
2 Likes