2009-10-01 8 views
1

J'ai vu cette question répondu dans d'autres langues mais pas le Korn Shell. Je dois empêcher qu'un script soit exécuté le dernier jour ouvrable du mois (nous pouvons supposer que M-F est un jour ouvrable, ignorer les jours fériés).Comment calculer le dernier jour ouvrable du mois à Korn Shell?

+0

Voir ma modification. J'ai ajouté une version qui ne nécessite pas 'date -d'. –

Répondre

2

Cette fonction fonctionne dans Bash, Korn shell et zsh, mais il nécessite une commande date (comme GNU date) qui a l'option -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; } 

Exécuter comme ceci:

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

Voici un script de démonstration divisé en lignes distinctes et avec de meilleurs noms de variables et des commentaires:

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 

Sortie:

 
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 

Note: J'ai découvert pendant le test que si vous essayez d'utiliser pour les dates autour de la Seconde Guerre mondiale qu'il échoue en raison des fuseaux horaires en temps de guerre comme CWT et CPT.

Édition: Voici une version qui devrait fonctionner sur AIX et d'autres systèmes qui ne peuvent pas utiliser ce qui précède. Ça devrait marcher sur Bourne, Bash, Korn et 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 }'; } 

Vous pouvez faire des ajustements si votre cal démarre semaines le lundi.

Voilà comment vous pouvez l'utiliser:

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 

faire des ajustements appropriés pour if de votre shell ... then syntaxe, bien sûr.

Modifier: Fix Bug: La version précédente de lbdN a échoué quand se termine le samedi Février 28 à cause de la façon dont il utilise tail. La nouvelle version corrige cela. Il utilise seulement cal et awk.

Édition: Pour être complet, j'ai pensé qu'il serait pratique d'inclure des fonctions pour le premier jour ouvrable du mois.

date avec -d Nécessite:

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"); } 

pour mai 2010:

Mon May 3 00:00:00 CDT 2010 

cal et awk Nécessite seulement:

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 }'; } 

Pour Août 2010:

2 
+0

Merci Dennis.J'apprécie vraiment votre aide. Malheureusement, ma commande "date" ne supporte pas l'option -d. Je cours ksh sur AIX 5.2. $ date -d "12/1/2009 -1 jours" Date : Pas un drapeau reconnu: d Utilisation: Date [-u] [+ "Descripteurs champ"] $ Je vais toujours cliquer sur le check-mark puisque votre solution fonctionne clairement sur d'autres systèmes, et je n'ai pas listé mon OS dans la question initiale. –

+0

Hmmm ... Il a sorti mes retours de chariot quand il a posté mon commentaire. Je suppose que je dois lire les documents sur la façon de formater mes commentaires. –

+0

Les commentaires ont un formatage très limité - pas de CR, par exemple. –

Questions connexes