Berechnung der Arbeitstage
Verfasst von Wolfgang Hornung am 30 Juli, 2010 - 14:00
Hallo zusammen,
hat jemand aus dem Forum eventuell ein Amkro zur Hand, mit man die Anzahl der
Arbeitstage zwischen 2 Datümern ermittlen kann? (Herr Kneilmann vielleicht ;-) )
Vielen Dank und viele Grüße
Wolfgang Hornung
»
- Anmelden oder Registrieren um Kommentare zu schreiben

Separate Tabelle mit arbeitsfreien Tagen
Hallo Herr Hornung,
das Problem liegt, wie Herr Kneilmann sagte, in der Definition, da ein Arbeitstag für jeden anders ist. Mir ist bislang auch nur die Variante bekannt, eine separate Tabelle zu führen, in die manuell für jedes Jahr die arbeitsfreien Tage eingetragen werden und gegen die dann abgeglichen wird.
Gruß Frederik Bloch
Jeder Tag ist ein Arbeitstag
Hallo Herr Hornung,
leider habe ich (früher wir, aber seit fast einem Jahr nur noch ich :-( )
dazu keinen Makro und auch überhaupt keinen Lösungsansatz.
Für mich ist das Problem grundsätzlicher Natur: Was ist ein Arbeitstag?
Ist der Samsatg ein Arbeitstag?
Was ist mit den Feiertagen?
Insbesondere den nicht bundeseinheitlichen?
Was ist mit den Feiertagen (europäischen) Ausland?
Wir sind bekanntlich ein Versandhandel mit fast 20 Filialen im Bundesgebiet, die früher auch Samstags geöffnet waren (also wäre Samstag ein Arbeitstag).
Ausserdem haben wir seit ewig den Online-Shop Schäfer Sohp, der ist sowiesso rund um die Uhr offen, folglich kommen jeden Tag Belege ins DWH (also wäre auch der Sonntag ein Arbeitstag).
Ausserdem haben wir Vertretungen im europäischen Ausland, insbesondere in AT und CH, dadurch ist auch am Feiertag keine Ruhe (also wäre auch fast jeder Feiertag ein Arbeitstag).
Für das DWH vom Schäfer Shop gibt es keinen Arbeitstag, weil jeder Tag ein Arbeitstag ist.
Tut mit leid, dass ich nicht weiterhelfen konnte.
Gruß
Hans Kneilmann, Schäfer Shop GmbH (SSI)
Ein Lösungsansatz
Hallo Herr Kneilmann, hallo Herr Bloch,
da habe Sie natürlich völlig recht, was ist überhaupt ein Arbeitstag.
Ich habe mir das ganze mal anhand der bundeseinheitlichen (fettgedruckt) Feiertage inkl. Heiligabend und Sylvester überlegt
und Samstag/Sonntag als arbeitsfrei definiert.
Die Feiertage unterteilen sich in datumsfixe (z.B. Neujahr) und solche deren Datum sich am Ostersonntag orientieren und
somit im Prinzip "mondfix" sind. Letztere kann man mit der Gauß'schen Osterformel ermitteln bzw. mit einer ergänzten
Formel nach Lichtenberg (s.a. Wikipedia: hier).
Anbei mein Ansatz, über Format gelöst:
data feiertage(keep=start fmtname label type);
length start $10;
retain fmtname 'feiertg' type 'c' label '0';
/* Datumsfixe Feiertage inkl. Heiligabend und Sylvester */
/* Neujahr, Maifeiertag, Tag der dt. Einheit, Heiligabend, 1.+2. Weihnachtsfeiertag, Sylvester */
array _feststehend(7) $ _temporary_ ('0101' '0105' '0310' '2412' '2512' '2612' '3112');
/* Datumsvariable bundeseinheitliche Feiertage, rel. zu Ostersonntag in Tagen */
/* Karfreitag, Ostermontag, Christi Himmelfahrt und Pfingstmonatg . */
array _beweglich(4) _temporary_ (-2 1 39 50);
format start;
do Jahr = 1990 to 2100;
/* Bundeseinheitliche feststehende Feiertage inkl. Heiligabend und Sylvester */
do i = 1 to 7;
monat=input(substr(_feststehend(i),3,2),2.);
tag=input(substr(_feststehend(i),1,2),2.);
start=put(mdy(monat,tag,jahr),ddmmyyp10.);
output;
end; /*************************************************************/
/* S.a. Wikipedia "Gauß'sche Osterformel" -> ergänzte Formel */
/* nach Lichtenberg */
/*-----------------------------------------------------------*/
A=mod(Jahr,19); /* Mondparameter */
K=floor(Jahr/100); /* Säkularzahl */
M=15+floor((3*K+3)/4)-floor((8*K+13)/25); /* Säkulare Mondschaltung */
D=mod(19*A+M,30); /* Keim für den ersten Vollmond im Frühling */
S=2-floor((3*K+3)/4); /* Säkulare Sonnenschaltung */
R=floor(D/29)+(floor(D/28)-floor(D/29))*floor(A/11); /* Kalendarische Korrekturgröße */
OG=21+D-R; /* Ostergrenze */
SZ=7-mod(Jahr+floor(Jahr/4)+S,7); /* Erster Sonntag im März */
OE=7-mod(OG-SZ,7); /* Osterentfernung vom ersten Sonntag im März in Tagen */
OS=OG+OE; /* Ostersonntag als Märzdatum (32. März = 1.April) */
/*************************************************************/
if OS>31 then do;
tag=OS-31;
monat=4;
do j = 1 to 4;
start=put(intnx('day',mdy(monat,tag,jahr),_beweglich(j)),ddmmyyp10.);
output;
end;
end;
else do;
tag=OE;
monat=3;
do j = 1 to 4;
start=put(intnx('day',mdy(monat,tag,jahr),_beweglich(j)),ddmmyyp10.);
output;
end;
end;
end;
start='other';
label='1';
output;
run;
proc format cntlin=feiertage lib=work;
run;
proc format;
value wtag
1 = '0' /* Sonntag */
7 = '0' /* Samstag */
other = '1' /* Wochentage */
;
run;
data test;
input von bis;
informat von bis ddmmyy10.;
cards;
01.12.2010 31.12.2010
01.01.2011 28.02.2011
01.04.2011 01.05.2011
;
run;
data arbeitstage(keep=von bis arbeitstage);
set test;
arbeitstage=0;
format von bis ddmmyyp10.;
do i = von to bis;
arbeitstage=arbeitstage+input(put(put(i,ddmmyyp10.),$feiertg.),1.)*input(put(input(put(i,weekday.),1.),wtag.),1.);
end;
run;
Viele Grüße
Wolfgang Hornung
Korrektur meines Lösungsansatzes
es hat sich ein Fehler unmittelbar nach der Ermittlung des Ostersonntages eingeschlichen.
Es muss heißen:
tag=OS; /* nicht tag=OE */
monat=3;
do j = 1 to 4;
start=put(intnx('day',mdy(monat,tag,jahr),_beweglich(j)),ddmmyyp10.);
output;
end;
end;
@Hr. Kneilmann: Ich hatte zunächst auch bei Ihnen in der Makro-Sammlung nachgeschaut.
Ich war allerding zu sehr auf den Begriff "Arbeitstag" fixiert.
Viele Grüße
Wolfgang Hornung
Fehler in der Fehler-Korrektur
Hallo Herr Hornung,
irgendetwas stimmt nicht mit der neuen Ermittlung des Ostersonntages!
Ich habe die Korrektur bei mir nachgezogen und bekomme einen Format-Fehler:
ERROR: This range is repeated, or values overlap: 01.05.2008-01.05.2008.
23142 run;
WARNING: RUN statement ignored due to previous errors. Submit QUIT; to terminate the procedure.
Das Datum 01.05.2008 ist tatsächlich doppelt im data set feiertage, also Fehler, oder?
Ein Vergleich der Daten alt und neu zeigt am Beispiel des Jahres 2008 deutliche Unterschiede:
alte Version:
28.02.2008 feiertg c 0
02.03.2008 feiertg c 0
09.04.2008 feiertg c 0
20.04.2008 feiertg c 0
01.05.2008 feiertg c 0
neue Version:
21.03.2008 feiertg c 0
24.03.2008 feiertg c 0
01.05.2008 feiertg c 0
01.05.2008 feiertg c 0
12.05.2008 feiertg c 0
*/
Wo liegt der Fehler?
Gruß
Hans Kneilmann, Schäfer Shop GmbH (SSI)
P.S.: Gefunden habe ich den Fehler, weil mir mittlerweile eine sinnvolle/nützliche Anwendungsmöglichkeit eingefallen ist :-)
Himmelfahrtproblem
Hallo Herr Kneilmann,
die Berechnung stimmt in der Tat, dazu ein Zitat aus Wikipedia:
"Im Jahre 2008 fiel Christi Himmelfahrt mit dem Feiertag „Tag der Arbeit“ (1. Mai) zusammen. Diese Konstellation tritt aber nur sehr selten ein, zuvor zuletzt im Jahr 1913 und nach 2008 erst wieder 2160."
Das Problem sollte also zu unseren Lebzeiten nur im Jahr 2008 (s.a. Kommentar von Lutz Ritter) auftauchen ;-)
Viele Grüße
Wolfgang Hornung
Himmelfahrt 2008
Hallo Herr Kneilmann,
ohne den Code von Herrn Hornung analysiert zu haben, denke ich daß die Berechnung korrekt ist. Der Termin von Himmelfahrt 2008 fiel tatsächlich auf den 01. Mai. Was die 2 Einträge für diesen Tag erklärt.
Abhilfe für Ihr Problem schafft somit ein kleines
by start ;
quit ;
Gruß
Lutz Ritter
Hallo zusammen, danke für die
Hallo zusammen,
danke für die Klarstellung, dass alles korrekt ist.
So ein
proc sort ... nodupkeyeinzufügen war nicht mein Problem. Die Unsicherheit, ob das Programm wirklich korrekte Werte liefert, das war mein Problem (wobei ich mir das nicht wirklich vorstellen konnte ...)Danke für den netten Tipp und vor allem Danke für die (beiden) Klarstellung(en), dass der 01.05.2008 tatsächlich doppelt auftreten darf.
Gruß
Hans Kneilmann, Schäfer Shop GmbH (SSI)
Super
Hallo Herr Hornung,
so wie in Ihrem Beitrag oben hätte ich auch den Arbeitstag definiert.
Das ist ja eine schöne Lösung und sogar komplett mit der Feiertags-Lösung. Die werde ich mir auf jeden Fall gut aufheben.
Die beweglichen Feiertage waren schon mal Thema im Redscope: Siehe Kalenderfrage zu Ostern
und in der Redscope-Makro-Sammlung unter
org.redscope.HansKneilmann.*
Gruß
Hans Kneilmann, Schäfer Shop GmbH (SSI)