Dieses Dokument wurde erstellt von Dr. Rolf Becker, SP Integration GmbH. Bestimmungsmethoden für die Generierung einer Zeitdimension In den Projekten von SP Integration kam von Kundenseite immer wieder der Wunsch nach einer einfach zu handhabenden Berechnungsmethodik zur Bestimmung einer Zeitdimension als Bestandteil des Kunden-Data-Warehouse auf. Die Dimensionstabelle sollte einerseits das Datum auflösen (Jahr, Monat, Tag, Wochentag, Quartal, Kalenderwoche usw.) und somit alle wesentlichen Bestandteile für die Bildung von Hierarchien insbesondere für OLAP Cubes bereitstellen (mit Visual Analytics lässt sich dieser Teil inzwischen mit wenigen Klicks generieren). Andererseits sollte sie feste und bewegliche Feiertage, Arbeitstage (in Monat und Jahr) und ggf. ein vom Kalenderjahr abweichendes Fiskaljahr (abweichende Jahres- und Monatswerte) beinhalten. So ist der im Anhang beigefügte SAS Code entstanden, der in Projekten zumeist als Generated Transformation für DI-Studio-Jobs den Kunden bereitgestellt wird. Die beweglichen Feiertage lassen sich vom Datum des Ostersonntags ableiten. Letzterer lässt sich über den von LICHENBERG (1997) modifizierten Ansatz von Gauss bestimmen. Dieser Ansatz wird von der Physikalisch-Technischen Bundesanstalt (PTB) verwendet, die vom Gesetzgeber den Auftrag erhalten hat, „die gesetzliche Zeit darzustellen und zu verbreiten“ (JURIS 2015). In Ihrem OnlineAngebot beschreibt die PTB (2015) den Lichtenberg‘schen Ansatz ausführlich, der sich in nachfolgendem SAS Code widerspiegelt: var_k = int(Jahr / 100); var_m = 15 + int((3 * var_k + 3) / 4) - int((8 * var_k + 13) / 25); var_s = 2 - int((3 * var_k + 3) / 4); var_a = Jahr - (19 * int(Jahr / 19)); var_d = (19 * var_a + var_m)- (30 * int((19 * var_a + var_m) / 30)); var_r = int(var_d / 29) + (int(var_d / 28) - int(var_d / 29)) * int(var_a / 11); var_og = 21 + var_d - var_r; var_sz = 7 - (Jahr + int(Jahr / 4) + var_s) - (7 * int((Jahr + int(Jahr / 4) + var_s)/ 7)); var_test = (7 * int((var_og - var_sz)/ 7)); var_oe = 7 - (var_og - var_sz) + (7 * int((var_og - var_sz)/ 7)); var_os = var_og + var_oe; if var_os <= 31 then Ostersonntag = mdy(3, var_os, Jahr); else Ostersonntag = mdy(4, (var_os - 31), Jahr); Die beweglichen Feiertage lassen sich wie folgt vom Datum des Ostersonntags ableiten: Karfreitag: Ostersonntag – 2 Tage Ostermontag: Ostersonntag + 1 Tag Christi Himmelfahrt: Ostersonntag + 39 Tage Pfingstsonntag: Ostersonntag + 49 Tage Pfingstmontag: Ostersonntag + 50 Tage Fronleichnam: Ostersonntag + 60 Tage Unter Einbeziehung der beweglichen und festen Feiertage sowie des Wochentags lässt sich dann leicht bestimmen, ob ein Datum innerhalb der Zeitdimension einen Arbeitstag repräsentiert oder nicht. Innerhalb des beigefügten SAS Codes werden die Anzahl der Arbeitstage als Year-to-Date (Arbeitstag_im_Jahr) bzw. Month-to-Date-Werte (Arbeitstag_im_Monat) in der Zeitdimension abgelegt. Literatur H. Lichtenberg (1997): Zur Interpretation der Gaußschen Osterformel und ihrer Ausnahmeregeln, Historia Mathematica 24, 441 - 444. JURIS (2015): Gesetz über die Einheiten im Messwesen und die Zeitbestimmung (Einheiten- und Zeitgesetz - EinhZeitG), Onlineangebot. PTB (2015): Wann ist Ostern; http://www.ptb.de/cms/fachabteilungen/abt4/fb-44/ag-441/darstellungder-gesetzlichen-zeit/wann-ist-ostern.html. Der gesamter Code /* ============================================================================== === */ /* erstellt durch: Dr. Rolf Becker */ /* Principal Consultant */ /* SP Integration GmbH */ /* Otto-Volger-Str. 5a */ /* 65843 Sulzbach (Taunus) */ /* +49 177 3164480 */ /* [email protected] */ /* erstellt am: 12.05.2015 */ /* zuletzt gaendert am: 12.05.2015 */ /* Beschreibung: Skript zum Erstellen der Zeitdimension */ /* - beweglicher Feiertage */ /* - Arbeitstage je Monat und Jahr */ /* - Fiskaljahr (optional) */ /* */ /* ============================================================================== === */ /* Aenderungsdatum / Aenderung */ /* durch wen */ /* */ /* ============================================================================== === */ %let _OUTPUT=DimTime; /*Zieldatei*/ %let u_StartDatum=01JAN1970; /*kleinstes Datum der Zeit-Dimension*/ %let u_EndDatum=31DEC2030; /*größtes Datum der Zeit-Dimension*/ %let u_MonatFiskaljahr=11; /*Ende des Fiskaljahrs (Monat)*/ proc format; value fWochentag 1 = 'Sonntag' 2 = 'Montag' 3 = 'Dienstag' 4 = 'Mittwoch' 5 = 'Donnerstag' 6 = 'Freitag' 7 = 'Samstag' ; run; proc format; value fMonat 1 = 'Januar' 2 = 'Februar' 3 = 'März' 4 = 'April' 5 = 'Mai' 6 = 'Juni' 7 = 'Juli' 8 = 'August' 9 = 'September' 10 = 'Oktober' 11 = 'November' 12 = 'Dezember' ; run; data &_OUTPUT(label='Zeitdimension' sortedby=Datum); keep Datum DateKey Wochentag_Nr Wochentag Monat_Nr Monat_Jahr Monat KW_Nr KW_Jahr Jahr Quartal Fiskal_Jahr Fiskal_Monat_Nr Fiskal_Quartal Tag_im_Monat Tag_im_Jahr Arbeitstag_im_Monat Arbeitstag_im_Jahr Feiertag_Flag Feiertag; length Datum DateKey Wochentag_Nr 8 Wochentag $10 Monat_Nr 8 Monat_Jahr Monat $9 KW_Nr 8 KW_Jahr $9 Jahr 8 Quartal $6 Fiskal_Jahr 8 Fiskal_Monat_Nr 8 Fiskal_Quartal $6 Tag_im_Monat Tag_im_Jahr Arbeitstag_im_Monat 8 Arbeitstag_im_Jahr Feiertag_Flag 8 Feiertag $30; format Datum ddmmyyp10.; do Datum="&u_StartDatum"d to "&u_EndDatum"d; DateKey = year(Datum) * 10000 + month(Datum) * 100 + day(Datum); Wochentag_Nr = weekday(Datum); Wochentag = put(Wochentag_Nr, fWochentag10.); Jahr = year(Datum); Monat_Nr = month(Datum); Monat_Jahr = put(Jahr,4.) !! '/' !! put(month(Datum),Z2.); Monat = put(Monat_Nr, fMonat9.); Quartal = put(Jahr,4.) !! 'Q' !! put(qtr(Datum),1.); KW_Nr = week(Datum, 'V'); KW_Jahr = put(Jahr,4.) !! '/' !! put(week(Datum,'V'),Z2.); if Monat_Nr <= &u_MonatFiskaljahr then do; Fiskal_Jahr = Year(Datum); Fiskal_Monat_Nr = month(Datum)+1; end; else do; Fiskal_Jahr = year(Datum)+1; Fiskal_Monat_Nr = 1; end; Fiskal_Quartal = compress(put(Fiskal_Jahr, 4.) !! 'Q' !! put(ceil(Fiskal_Monat_Nr/3),1.)); Tag_im_Monat = day(Datum); if Monat_Nr = 1 and Tag_im_Monat = 1 then Tag_im_Jahr = 1; else Tag_im_Jahr = Tag_im_Jahr + 1; /* bewegliche Feiertage - Berechnung des Ostermsonntags nach Gauss, modifiziert von Lichtenberg */ /* H. Lichtenberg (1997): Zur Interpretation der Gaußschen Osterformel und ihrer Ausnahmeregeln, Historia Mathematica 24, 441 - 444. */ /* http://www.ptb.de/cms/fachabteilungen/abt4/fb-44/ag-441/darstellung-der-gesetzlichen-zeit/wannist-ostern.html */ var_k = int(Jahr / 100); var_m = 15 + int((3 * var_k + 3) / 4) - int((8 * var_k + 13) / 25); var_s = 2 - int((3 * var_k + 3) / 4); var_a = Jahr - (19 * int(Jahr / 19)); var_d = (19 * var_a + var_m)- (30 * int((19 * var_a + var_m) / 30)); var_r = int(var_d / 29) + (int(var_d / 28) - int(var_d / 29)) * int(var_a / 11); var_og = 21 + var_d - var_r; var_sz = 7 - (Jahr + int(Jahr / 4) + var_s) - (7 * int((Jahr + int(Jahr / 4) + var_s)/ 7)); var_test = (7 * int((var_og - var_sz)/ 7)); var_oe = 7 - (var_og - var_sz) + (7 * int((var_og - var_sz)/ 7)); var_os = var_og + var_oe; if var_os <= 31 then Ostersonntag = mdy(3, var_os, Jahr); else Ostersonntag = mdy(4, (var_os - 31), Jahr); /*bewegliche Feiertage (Hessen)*/ if Datum = Ostersonntag then do; Feiertag_Flag = 1; Feiertag = 'Ostersonntag'; end; else if Datum = Ostersonntag - 2 then do; Feiertag_Flag = 1; Feiertag = 'Kafreitag'; end; else if Datum = Ostersonntag + 1 then do; Feiertag_Flag = 1; Feiertag = 'Ostermontag'; end; else if Datum = Ostersonntag + 39 then do; Feiertag_Flag = 1; Feiertag = 'Christi Himmelfahrt'; end; else if Datum = Ostersonntag + 49 then do; Feiertag_Flag = 1; Feiertag = 'Pfingstsonntag'; end; else if Datum = Ostersonntag + 50 then do; Feiertag_Flag = 1; Feiertag = 'Pfingstmontag'; end; else if Datum = Ostersonntag + 60 then do; Feiertag_Flag = 1; Feiertag = 'Fronleichnahm'; end; /* feste Feiertage (Hessen) */ else if Monat_Nr = 1 and Tag_im_Monat = 1 then do; Feiertag_Flag = 1; Feiertag = 'Neujahr'; end; else if Monat_Nr = 5 and Tag_im_Monat = 1 then do; Feiertag_Flag = 1; Feiertag = 'Maifeiertag'; end; else if Monat_Nr = 10 and Tag_im_Monat = 3 then do; Feiertag_Flag = 1; Feiertag = 'Tag der deutschen Einheit'; end; else if Monat_Nr = 12 and Tag_im_Monat = 25 then do; Feiertag_Flag = 1; Feiertag = '1. Weihnachtsfeiertag'; end; else if Monat_Nr = 12 and Tag_im_Monat = 26 then do; Feiertag_Flag = 1; Feiertag = '2. Weihnachtsfeiertag'; end; else do; Feiertag_Flag = 0; Feiertag = ''; end; /* Arbeitstage */ if Monat_Nr = 1 and Tag_im_Monat = 1 then do; if Wochentag_Nr not in (1,7) and Feiertag_Flag = 0 then do; Arbeitstag_im_Jahr = 1; Arbeitstag_im_Monat = 1; end; else do; Arbeitstag_im_Jahr = 0; Arbeitstag_im_Monat = 0; end; end; else if Tag_im_Monat = 1 then do; if Wochentag_Nr not in (1,7) and Feiertag_Flag = 0 then do; Arbeitstag_im_Monat = 1; Arbeitstag_im_Jahr = Arbeitstag_im_Jahr + 1; end; else Arbeitstag_im_Monat = 0; end; else do; if Wochentag_Nr not in (1,7) and Feiertag_Flag = 0 then do; Arbeitstag_im_Monat = Arbeitstag_im_Monat + 1; Arbeitstag_im_Jahr = Arbeitstag_im_Jahr + 1; end; end; Output; end; run; SAS INSTITUTE GMBH IN DER NECKARHELLE 162 69118 HEIDELBERG Phone: +49 6221 415-0 Fax: +49 6221 415-101 www.sas.com/deutschland Eine Tochtergesellschaft von SAS Institute Inc., SAS Circle, Box 8000, Cary, NC 27512-8000, USA. Sitz der Gesellschaft Heidelberg, Registergericht Mannheim, HRB 332269, Geschäftsführer Wolf Lichtenstein, Finanzamt Heidelberg, Steuer-Nr. 32497/83950.
© Copyright 2024 ExpyDoc