Benutzer-Werkzeuge

Webseiten-Werkzeuge


comp:ftagebash

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

comp:ftagebash [2014-08-12 1702] (aktuell)
werner angelegt
Zeile 1: Zeile 1:
 +====== Bash: Feiertage ======
 +
 +Der folgende Code ist entstanden, als es galt, eine Feiertagsprüfung in Bash (wahlweise AWK) umzusetzen. Also habe ich mal die Feiertage für Sachsen und Sachsen-Anhalt berechnen lassen... Ist nicht schnell, aber funktioniert.
 +
 +Historisch gesehen, habe ich das zum ersten Mal Ende der 80er Jahre in Pascal geschrieben, später in VBA für Excel 5.0 (deutsch), Excel 97 (englisch), PHP, Perl, ... und nun eben zum ersten Mal in Bash :-)
 +
 +<file bash /usr/local/bin/kalender.sh>
 +#!/bin/bash
 +
 +# Funktionssammlung fuer Kalenderzwecke
 +# checkJahr $JAHR
 +# checkMonat $MONAT
 +# checkTag $TAG $MONAT $JAHR
 +# is_Leapyear $JAHR
 +# cal_days_in_month $MONAT $JAHR
 +# getKarfreitag $JAHR
 +# getOstersonntag $JAHR
 +# getOstermontag $JAHR
 +# getHimmelfahrt $JAHR
 +# getAdvent1 $JAHR
 +# getAdvent2 $JAHR
 +# getAdvent3 $JAHR
 +# getAdvent4 $JAHR
 +# getWochentag $TAG $MONAT $JAHR
 +# istFeiertag $TAG $MONAT $JAHR
 +
 +EWIGERKALENDER='ewkal.sh'
 +[ -f "$EWIGERKALENDER" ] && . "$EWIGERKALENDER"
 +
 +# testet, ob das angegebene Jahr eine vierstellige Zahl und mindestens 1683 ist
 +# Param1: Jahreszahl
 +# Rückgabe: 1 bei Fehler, 0 wenn OK
 +#           außerdem wird $? gesetzt
 +checkJahr() {
 +    # integer, > 1683
 +    TESTJAHR=${1:-0}
 +    VERSJ=$(echo "$TESTJAHR" | tr -d '[0-9]')
 +    [ -z "$VERSJ" ] || return 1
 +    if [[ $TESTJAHR =~ ^[0-9]+$ ]] && [ $TESTJAHR -gt 1683 ]; then
 +        echo 0
 +        return 0
 +    else
 +        echo 1
 +        return 1
 +    fi
 +} # checkJahr
 +
 +# testet, ob der angegebene Jahr Monat im Bereich 1 bis 12 liegt
 +# Param1: Monatsnummer
 +# Rückgabe: 1 bei Fehler, 0 wenn OK
 +#           außerdem wird $? gesetzt
 +checkMonat() {
 +    # integer, Bereich 1..12
 +    TESTMONAT=${1:-0}
 +    if [[ $TESTMONAT =~ ^[0-9]+$ ]] && [ $TESTMONAT -ge 1 -a $TESTMONAT -le 12 ]; then
 +        echo 0
 +        return 0
 +    else
 +        echo 1
 +        return 1
 +    fi
 +} # checkMonat
 +
 +# teste, ob es sich um ein Schaltjahr handelt
 +# Param1: Jahreszahl
 +# Rückgabe: Text 0 bei Fehler, Text 1 wenn OK
 +#           außerdem wird $? gesetzt
 +is_Leapyear() {
 +    RETVAL=9
 +    TESTJAHR=${1:-0}
 +    JAHR_OK=$(checkJahr $TESTJAHR)
 +    if [ "x$JAHR_OK" != 'x0' ]; then
 +        echo $RETVAL
 +        return $RETVAL
 +    fi
 +    if [ $(($TESTJAHR % 100)) -ne 0 -a  $(($TESTJAHR % 4)) -eq 0 ]; then
 +        RETVAL=1
 +    elif [ $(($TESTJAHR % 400)) == 0 ]; then
 +        RETVAL=1
 +    else
 +        RETVAL=0
 +    fi
 +    echo $RETVAL
 +    return $RETVAL
 +} # is_Leapyear
 +
 +# Anzahl Tage im Kalendermonat
 +# Param1: Monatszahl, siehe checkMonat
 +# Param2: Jahreszahl, siehe checkJahr
 +# Rückgabe: eine Zahl im Bereich 28..31, je nachdem :-)
 +#           im Fehlerfall eine 1 (Errorlevel wird gesetzt)
 +cal_days_in_month() {
 +    TESTMONAT=${1:-0}
 +    TESTJAHR=${2:-0}
 +    JAHR_OK=$(checkJahr $TESTJAHR)
 +    MONAT_OK=$(checkMonat $TESTMONAT)
 +    if [ "x$JAHR_OK" != 'x0' -o "x$MONAT_OK" != 'x0' ]; then
 +        echo 1
 +        return 1
 +    fi
 +    case $TESTMONAT in
 +        1|3|5|7|8|10|12)        RETVAL=31       ;;
 +        4|6|9|11)               RETVAL=30       ;;
 +        2)                      if [ is_Leapyear $TESTJAHR ]; then
 +                                    RETVAL=29
 +                                else
 +                                    RETVAL=28
 +                                fi
 +                                                ;;
 +    esac
 +    echo $RETVAL
 +} # cal_days_in_month
 +
 +# testet, ob ein Tag im erlaubten Bereich (Monatslänge) ist
 +# Param1: Tageszahl
 +# Param2: Monatszahl, siehe checkMonat
 +# Param3: Jahreszahl, siehe checkJahr
 +# Rückgabe: Tageszahl (Param1), wenn Tag möglich ist
 +#           sonst letzter Tag des Monats
 +#           $? = 0, wenn Tag möglich ist, 1 sonst
 +checkTag() {
 +    TESTTAG=${1:-0}
 +    TESTMONAT=${2:-0}
 +    TESTJAHR=${3:-0}
 +    [ "x${TESTTAG:0:1}"   = 'x0' ] && TESTTAG="${TESTTAG:1:1}"
 +    [ "x${TESTMONAT:0:1}" = 'x0' ] && TESTMONAT="${TESTMONAT:1:1}"
 +#    echo "testjahr=$TESTJAHR, testmonat=$TESTMONAT (x${TESTMONAT:0:2}), testtag=$TESTTAG" >> /tmp/jahr4
 +    TAG_OK=$(echo $TESTTAG | tr -d [0-9])
 +#    if [[ $TESTTAG =~ ^[0-9]+$ ]] && [[ $TESTTAG -lt 1 ]]; then
 +    let "TESTTAG *= 1"
 +    if [ -z "$TAG_OK" -a $TESTTAG -ge 1 ]; then
 +        :
 +    else
 +        echo 1
 +        return 1
 +    fi
 +    JAHR_OK=$(checkJahr $TESTJAHR)
 +    if [ "x$JAHR_OK" != "x0" ]; then
 +        echo 2
 +        return 1
 +    fi
 +    MON_OK=$(checkMonat $TESTMONAT)
 +    if [ "x$MON_OK" != 'x0' ]; then
 +        echo 3
 +        return 1
 +    fi
 +    MAXTAGE=$(cal_days_in_month $TESTMONAT $TESTJAHR)
 +    if [ $MAXTAGE -ge $TESTTAG ]; then
 +        echo $TESTTAG
 +        return 0
 +    else
 +        echo $MAXTAGE
 +        return 1
 +    fi
 +} # checkTag
 +
 +# berechnet das Osterdatum nach Gauss
 +# Param1: Jahreszahl, siehe checkJahr
 +# Rückgabe: Ostersonntag im Format YYYY-MM-DD
 +getOstersonntag() {
 +    TESTJAHR=${1:-0}
 +    [ $TESTJAHR -eq 0 ] && TESTJAHR=$(date +%Y)
 +    G=$(expr $TESTJAHR % 19 + 1)
 +    C=$(expr $TESTJAHR / 100 + 1)
 +    X=$(expr \( $C / 4 - 4 \) \* 3)
 +    Z=$(expr \( $C \* 8 + 5 \) / 25 - 5)
 +    D=$(expr $TESTJAHR \* 5 / 4 - $X - 10)
 +    E=$(expr \( $G \* 11 + $Z - $X + 20 \) % 30)
 +    [ $E -lt 0 ] && E=$(expr $E + 30)
 +    [ $E -eq 25 -a $G -gt 11 -o $E -eq 24 ] && E=$(expr $E + 1)
 +    TAG=$(expr 44 - $E)
 +    [ $TAG -lt 21 ] && TAG=$(expr $TAG + 30)
 +    TAG=$(expr $TAG + 7 - \( $D + $TAG \) % 7)
 +    if [ $TAG -gt 31 ] ; then
 +       TAG=$(expr $TAG - 31)
 +       MON=4
 +    else
 +       MON=3
 +    fi
 +    echo "$TESTJAHR-$MON-$TAG"
 +} # getOstersonntag
 +
 +# berechnet das Datum des 1. Advent
 +# Param1: Jahreszahl, siehe checkJahr
 +# Rückgabe: Datum im Format YYYY-MM-DD
 +getAdvent1() {
 +    DJHR=$1
 +    # numerisch?
 +    TSTJHR=$(echo "DJHR" | tr -d '[0-9]')
 +    [ -z "$TSTJHR" ] || DJHR=$(date +%Y)
 +    # lang genug?
 +    [ "x${#DJHR}" = 'x4'  ] || DJHR=$(date +%Y)
 +    DMON=11
 +    DTAG=27
 +    ZIELWOTAG='So'
 +    ISTWOTAG=$(getWochentag $DTAG $DMON $DJHR)
 +    while [ "$ZIELWOTAG" != "$ISTWOTAG" ]; do
 +        STICHSEK=$(date -d "${DJHR}-${DMON}-${DTAG}" +%s)
 +        let "STICHSEK += 86400"
 +        DTAG=$(date -d "@$STICHSEK" +%d)
 +        DMON=$(date -d "@$STICHSEK" +%m)
 +        ISTWOTAG=$(getWochentag $DTAG $DMON $DJHR)
 +    done
 +    date -d "@$STICHSEK" +'%Y-%m-%d'
 +} # getAdvent1
 +
 +# berechnet das Datum des 2. Advent
 +# Param1: Jahreszahl, siehe checkJahr
 +# Rückgabe: Datum im Format YYYY-MM-DD
 +getAdvent2() {
 +    DJHR=$1
 +    # numerisch?
 +    TSTJHR=$(echo "DJHR" | tr -d '[0-9]')
 +    [ -z "$TSTJHR" ] || DJHR=$(date +%Y)
 +    # lang genug?
 +    [ "x${#DJHR}" = 'x4'  ] || DJHR=$(date +%Y)
 +    # Basis: 1. Advent
 +    ADV1=$(getAdvent1 $DJHR)
 +    SEKDAT=$(date -d "$ADV1" +%s)
 +    # plus eine Woche
 +    DIFF=$((7 * 86400))
 +    let "SEKDAT += DIFF"
 +    date -d "@$SEKDAT"  +'%Y-%m-%d'
 +} # getAdvent2
 +
 +# berechnet das Datum des 3. Advent
 +# Param1: Jahreszahl, siehe checkJahr
 +# Rückgabe: Datum im Format YYYY-MM-DD
 +getAdvent3() {
 +    DJHR=$1
 +    # numerisch?
 +    TSTJHR=$(echo "DJHR" | tr -d '[0-9]')
 +    [ -z "$TSTJHR" ] || DJHR=$(date +%Y)
 +    # lang genug?
 +    [ "x${#DJHR}" = 'x4'  ] || DJHR=$(date +%Y)
 +    # Basis: 1. Advent
 +    ADV1=$(getAdvent1 $DJHR)
 +    SEKDAT=$(date -d "$ADV1" +%s)
 +    # plus zwei Wochen
 +    DIFF=$((2 * 7 * 86400))
 +    let "SEKDAT += DIFF"
 +    date -d "@$SEKDAT"  +'%Y-%m-%d'
 +} # getAdvent3
 +
 +# berechnet das Datum des 4. Advent
 +# Param1: Jahreszahl, siehe checkJahr
 +# Rückgabe: Datum im Format YYYY-MM-DD
 +getAdvent4() {
 +    DJHR=$1
 +    # numerisch?
 +    TSTJHR=$(echo "DJHR" | tr -d '[0-9]')
 +    [ -z "$TSTJHR" ] || DJHR=$(date +%Y)
 +    # lang genug?
 +    [ "x${#DJHR}" = 'x4'  ] || DJHR=$(date +%Y)
 +    # Basis: 1. Advent
 +    ADV1=$(getAdvent1 $DJHR)
 +    SEKDAT=$(date -d "$ADV1" +%s)
 +    # plus drei Wochen
 +    DIFF=$((3 * 7 * 86400))
 +    let "SEKDAT += DIFF"
 +    date -d "@$SEKDAT"  +'%Y-%m-%d'
 +} # getAdvent4
 +
 +# berechnet das Datum des Buß- und Bettags
 +# Param1: Jahreszahl, siehe checkJahr
 +# Rückgabe: Datum im Format YYYY-MM-DD
 +getBusstag() {
 +    DJHR=$1
 +    # numerisch?
 +    TSTJHR=$(echo "$DJHR" | tr -d '[0-9]')
 +    [ -z "$TSTJHR" ] || DJHR=$(date +%Y)
 +    # lang genug?
 +    [ "x${#DJHR}" = 'x4'  ] || DJHR=$(date +%Y)
 +    # Basis: 1. Advent
 +    ADV1=$(getAdvent1 $DJHR)
 +    SEKDAT=$(date -d "$ADV1" +%s)
 +    # minus 10 tage
 +    DIFF=$((10 * 86400))
 +    let "SEKDAT -= $DIFF"
 +    date -d "@$SEKDAT"  +'%Y-%m-%d'
 +} # getBusstag
 +
 +# berechnet das Datum des Ostermontags
 +# Param1: Jahreszahl, siehe checkJahr
 +# Rückgabe: Datum im Format YYYY-MM-DD
 +getOstermontag() {
 +    ODAT=$1
 +    [ -z "$ODAT" ] && return 1
 +    # in Sekunden umwandeln
 +    OSONN=$(date -d "$ODAT" +%s)
 +    # Differenz hinzu
 +    OMONTAG=$(($OSONN + 86400))
 +    # im Format YYYY-MM-DD ausgeben
 +    date -d "@$OMONTAG" +'%Y-%m-%d'
 +} # getOstermontag
 +
 +# berechnet das Datum des Karfreitags
 +# Param1: Jahreszahl, siehe checkJahr
 +# Rückgabe: Datum im Format YYYY-MM-DD
 +getKarfreitag() {
 +    ODAT=$1
 +    [ -z "$ODAT" ] && return 1
 +    # in Sekunden umwandeln
 +    OSONN=$(date -d "$ODAT" +%s)
 +    # Differenz hinzu
 +    SEKDIFF=$((2 * 86400))
 +    KARFTAG=$(($OSONN + $SEKDIFF))
 +    # im Format YYYY-MM-DD ausgeben
 +    date -d "@$KARFTAG" +'%Y-%m-%d'
 +} # getKarfreitag
 +
 +# berechnet das Datum des Pfingstsonntags
 +# Param1: Jahreszahl, siehe checkJahr
 +# Rückgabe: Datum im Format YYYY-MM-DD
 +getPfingstsonntag() {
 +    ODAT=$1
 +    [ -z "$ODAT" ] && return 1
 +    # in Sekunden umwandeln
 +    OSONN=$(date -d "$ODAT" +%s)
 +    # Differenz hinzu
 +    SEKDIFF=$((49 * 86400))
 +    PFSONN=$(($OSONN + $SEKDIFF))
 +    # im Format YYYY-MM-DD ausgeben
 +    date -d "@$PFSONN" +'%Y-%m-%d'
 +} # getPfingstsonntag
 +
 +# berechnet das Datum des Pfingstmontags
 +# Param1: Jahreszahl, siehe checkJahr
 +# Rückgabe: Datum im Format YYYY-MM-DD
 +getPfingstmontag() {
 +    ODAT=$1
 +    [ -z "$ODAT" ] && return 1
 +    # in Sekunden umwandeln
 +    OSONN=$(date -d "$ODAT" +%s)
 +    # Differenz hinzu
 +    SEKDIFF=$((50 * 86400))
 +    PFMON=$(($OSONN + $SEKDIFF))
 +    # im Format YYYY-MM-DD ausgeben
 +    date -d "@$PFMON" +'%Y-%m-%d'
 +} # getPfingstmontag
 +
 +# berechnet das Datum von Christi Himmelfahrt
 +# Param1: Jahreszahl, siehe checkJahr
 +# Rückgabe: Datum im Format YYYY-MM-DD
 +getHimmelfahrt() {
 +    ODAT=$1
 +    [ -z "$ODAT" ] && return 1
 +    # in Sekunden umwandeln
 +    OSONN=$(date -d "$ODAT" +%s)
 +    # Differenz hinzu
 +    SEKDIFF=$((39 * 86400))
 +    HIFAH=$(($OSONN + $SEKDIFF))
 +    # im Format YYYY-MM-DD ausgeben
 +    date -d "@$HIFAH" +'%Y-%m-%d'
 +} # getHimmelfahrt
 +
 +# prüft, ob es sich beim übergebenen Datum um einen Feiertag handelt
 +# Param1: Tageszahl, siehe checkTag
 +# Param2: Monatszahl, siehe checkMonat
 +# Param3: Jahreszahl, siehe checkJahr
 +# Param4: Region; 'SN' -> Sachsen, 'SA' -> Sachsen-Anhalt
 +# Rückgabe: 1 wenn Feiertag, 0 sonst
 +#           $? wird entsprechend gesetzt
 +istFeiertag() {
 +    TAG=${1:-0}
 +    MONAT=${2:-0}
 +    JAHR=${3:-0}
 +    INREGION=${4:-'SN'}
 +    RETID=0
 +    [ "x$JAHR"  = "x0" ] && JAHR=$(date +%Y)
 +    [ "x$MONAT" = "x0" ] && MONAT=$(date +%m)
 +    [ "x$TAG"   = "x0" ] && TAG=$(date +%d)
 +    JAHR_OK=$(checkJahr $JAHR)
 +    if [ "x$JAHR_OK" != 'x0'  ]; then
 +        echo 0
 +        return 1
 +    fi
 +    [ "x${TAG:0:1}" = 'x0' ] && TAG=${TAG:1:1}
 +    [ "x${MON:0:1}" = 'x0' ] && MON=${MON:1:1}
 +    VGLTAG=$(checkTag $TAG $MONAT $JAHR)
 +    [ $VGLTAG -ne $TAG ] && return 1
 +    FEIER=0
 +    if [ $MONAT -eq 12 ]; then
 +        case "$TAG" in
 +            24|25|26|31)
 +                FEIER=1
 +                ;;
 +        esac
 +    elif [ $MONAT -eq 10 ]; then
 +        case $TAG in
 +            3|31)
 +                FEIER=1
 +                ;;
 +        esac
 +    elif [ $MONAT -eq 5 -a $TAG -eq 1 ]; then
 +        FEIER=1
 +    elif [ $MONAT -eq 1 -a $TAG -eq 1 ]; then
 +        FEIER=1
 +    fi
 +    if [ $FEIER -eq 0 ]; then
 +        VGLDAT="${JAHR}-${MONAT}-${TAG}"
 +        # jetzt die beweglichen Feiertage
 +        # Lassen wir die Sonntage mal raus ;-)
 +        KFDAT=$(getKarfreitag $JAHR)
 +#        OSDAT=$(getOstersonntag $JAHR)
 +        OMDAT=$(getOstermontag $JAHR)
 +        HFDAT=$(getHimmelfahrt $JAHR)
 +#        PSDAT=$(getPfingstsonntag $JAHR)
 +        PMDAT=$(getPfingstmontag $JAHR)
 +#        A1DAT=$(getAdvent1 $JAHR)
 +#        A2DAT=$(getAdvent2 $JAHR)
 +#        A3DAT=$(getAdvent3 $JAHR)
 +#        A4DAT=$(getAdvent4 $JAHR)
 +        if [ "$VGLDAT" = "$KFDAT" ]; then
 +            FEIER=1
 +#               elif [ "$VGLDAT" = "$OSDAT" ]; then
 +#                       FEIER=1
 +        elif [ "$VGLDAT" = "$OMDAT" ]; then
 +            FEIER=1
 +        elif [ "$VGLDAT" = "$HFDAT" ]; then
 +            FEIER=1
 +#               elif [ "$VGLDAT" = "$PSDAT" ]; then
 +#                       FEIER=1
 +        elif [ "$VGLDAT" = "$PMDAT" ]; then
 +            FEIER=1
 +#               elif [ "$VGLDAT" = "$A1DAT" ]; then
 +#                       FEIER=1
 +#               elif [ "$VGLDAT" = "$A2DAT" ]; then
 +#                       FEIER=1
 +#               elif [ "$VGLDAT" = "$A3DAT" ]; then
 +#                       FEIER=1
 +#               elif [ "$VGLDAT" = "$A4DAT" ]; then
 +#                       FEIER=1
 +        fi
 +    fi
 +    if [ $FEIER -eq 0 ]; then
 +        # jetzt die bundeslandabhängigen Feiertage
 +        if [ "$INREGION" = 'SN' ]; then
 +            BBDAT=$(getBusstag $JAHR)
 +            if [ "x$VGLDAT" = "x$BBDAT" ]; then
 +                FEIER=1
 +            fi
 +        else
 +            if [ "$VGLDAT" = "${JAHR}-01-06" ]; then
 +                FEIER=1
 +            fi
 +        fi
 +    fi
 +    echo "$FEIER"
 +    return $FEIER
 +} # istFeiertag
 +</file>
  
comp/ftagebash.txt · Zuletzt geändert: 2014-08-12 1702 von werner