Domanda

Ho visto questa domanda ha risposto in altre lingue, ma non la Korn Shell. Ho bisogno di evitare che uno script viene eseguito l'ultimo giorno lavorativo del mese (possiamo supporre M-F sono giorni lavorativi, ignorare i giorni festivi).

È stato utile?

Soluzione

Questa funzione lavora a Bash, Korn shell e zsh, ma richiede un comando date (come GNU date) che ha l'opzione -d:

function lbdm { typeset lbdm ldm dwn m y; (( m = $1 + 1 )); if [[ $m = 13 ]]; then  m=1; (( y = $2 + 1 )); else y=$2; fi; ldm=$(date -d "$m/1/$y -1 day"); dwn=$(date -d "$ldm" +%u);if [[ $dwn = 6 || $dwn = 7 ]]; then ((offset = 5 - $dwn)); lbdm=$(date -d "$ldm $offset day"); else lbdm=$ldm; fi; echo $lbdm; }

Esegui in questo modo:

$ lbdm 10 2009
Fri Oct 30 00:00:00 CDT 2009

Ecco uno script demo suddiviso in linee separate e con migliori nomi delle variabili e alcuni commenti:

for Month in {1..12}   # demo a whole year 
do 
    Year=2009
    LastBusinessDay=""
    (( Month = $Month + 1 ))    # use the beginning of the next month to find the end of the one we're interested in
    if [[ $Month = 13 ]]
    then
        Month=1
        (( Year++ ))
    fi;
    # these two calls to date could be combined and then parsed out
    # this first call is in "American" order, but could be changed - everything else is localized - I think
    LastDayofMonth=$(date -d "$Month/1/$Year -1 day")    # get the day before the first of the month
    DayofWeek=$(date -d "$LastDayofMonth" +%u)    # the math is easier than Sun=0 (%w)
    if [[ $DayofWeek = 6 || $DayofWeek = 7 ]]    # if it's Sat or Sun
    then
        (( Offset = 5 - $DayofWeek ))    # then make it Fri
        LastBusinessDay=$(date -d "$LastDayofMonth $Offset day")
    else
        LastBusinessDay=$LastDayofMonth
    fi
    echo "$LastDayofMonth - $DayofWeek - $LastBusinessDay"
done

Output:

Sat Jan 31 00:00:00 CST 2009 - 6 - Fri Jan 30 00:00:00 CST 2009
Sat Feb 28 00:00:00 CST 2009 - 6 - Fri Feb 27 00:00:00 CST 2009
Tue Mar 31 00:00:00 CDT 2009 - 2 - Tue Mar 31 00:00:00 CDT 2009
Thu Apr 30 00:00:00 CDT 2009 - 4 - Thu Apr 30 00:00:00 CDT 2009
Sun May 31 00:00:00 CDT 2009 - 7 - Fri May 29 00:00:00 CDT 2009
Tue Jun 30 00:00:00 CDT 2009 - 2 - Tue Jun 30 00:00:00 CDT 2009
Fri Jul 31 00:00:00 CDT 2009 - 5 - Fri Jul 31 00:00:00 CDT 2009
Mon Aug 31 00:00:00 CDT 2009 - 1 - Mon Aug 31 00:00:00 CDT 2009
Wed Sep 30 00:00:00 CDT 2009 - 3 - Wed Sep 30 00:00:00 CDT 2009
Sat Oct 31 00:00:00 CDT 2009 - 6 - Fri Oct 30 00:00:00 CDT 2009
Mon Nov 30 00:00:00 CST 2009 - 1 - Mon Nov 30 00:00:00 CST 2009
Thu Dec 31 00:00:00 CST 2009 - 4 - Thu Dec 31 00:00:00 CST 2009

. Nota: ho scoperto durante la prova che se si tenta di utilizzare questo per date in giro per la seconda guerra mondiale che non riesce a causa di fusi orari in tempo di guerra come CWT e CPT

Modifica : Ecco una versione che dovrebbe funzionare su AIX e altri sistemi che non possono utilizzare quanto sopra. Dovrebbe funzionare su Bourne, Bash, Korn e zsh.

function lbdN { cal $1 $2 | awk 'NF == 0 {next} FNR > 2 {week = $0} END {num = split(week, days); lbdN = days[num]; if ( num == 1 ) { lbdN -= 2 }; if ( num == 7 ) { lbdN-- }; print lbdN }'; }

Potrebbe essere necessario apportare modifiche se il vostro cal inizia settimane il Lunedi.

Ecco come si può utilizzare:

month=12; year=2009    # if these are unset or null, the current month/year will be used
if [[ $(date +%d) == $(lbdN $month $year) ]]; 
then
    echo "Don't do stuff today"
else
    echo "It's not the last business day of the month"
fi

fare aggiustamenti appropriati per la sintassi if ... then della shell, naturalmente.

Modifica : Bug Fix : La versione precedente di lbdN fallì quando febbraio termina il Sabato 28 a causa del modo in passato tail. La nuova versione corregge questo. Si utilizza solo cal e awk.

Modifica :. Per completezza, ho pensato che sarebbe stato utile per comprendere le funzioni per il primo giorno lavorativo del mese

Richiede date con -d:

function fbdm { typeset dwn d; dwn=$(date -d "$1/1/$2" +%u); d=1; if [[ $dwn = 6 || $dwn = 7 ]]; then (( d = 9 - $dwn )); fi; echo $(date -d "$1/$d/$2"); }

Per maggio 2010:

Mon May 3 00:00:00 CDT 2010

Richiede cal e awk solo:

function fbdN { cal $1 $2 | awk 'FNR == 3 { week = $0 } END { num = split(week, days); fbdN = days[1]; if ( num == 1 ) { fbdN += 2 }; if ( num == 7 ) { fbdN++ }; print fbdN }'; }

Per agosto 2010:

2
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top