Datum Problem
Verfasst von cailloux am 20 Juni, 2008 - 08:03
Hallo,
folgendes Problem habe ich : bei dem anbei in Kode geschafften SAS Datei "toto" befinden sich 2 Datum date_A und date_B, aus denen ich mithilfe der datdif Funktion eine Anzahl an Tagen berechnet, die diese 2 Datum unterscheidet.
Jetzt hat mir aber ein Kollege nur den Datum_A und die diff_A_B Variable, und ich muss daraus das Datum date_B wiederhestellen (also die datdif Funktion rückwirkend machen).
Wer kann da eine elegante Lösung dafür finden ?
data toto ;
format date_A date_B date9. ;
date_A = '17mar2007'd ;
date_B = '28jun2007'd ;
Diff_A_B = datDif(date_A, date_B,'30/360') ;
run ;
format date_A date_B date9. ;
date_A = '17mar2007'd ;
date_B = '28jun2007'd ;
Diff_A_B = datDif(date_A, date_B,'30/360') ;
run ;
»
- Anmelden oder Registrieren um Kommentare zu schreiben

mit 30/360
Wenn man die spezielle Rechenweise bei 30/360 berücksichtigt, ist es nicht ganz so einfach. Das folgende Programm berechnet zunächst eine Näherungslösung und korrigiert diese dann anhand der datDif-Funktion. Das hat den Vorteil, dass man nicht so genau wissen muss, wie die datDig-Funktion wirklich funktioniert. Der Nachteil ist, dass man beim vorwärts-rückwärts-rechnen nicht immer beim gleichen Datum landet, wie die Programmdaten zeigen. Zum Beispiel erhält man aus datDif('17mar2007'd,'01jun2007'd) das gleiche wie aus datDif('17mar2007'd,'31may2007'd), nämlich 74.
format date_A date_B date9. ;
informat date_A date_B date9. ;
input date_A date_B;
Diff_A_B = datDif(date_A, date_B,'30/360') ;
output;
datalines;
17mar2007 28jun2007
31mar2007 28jun2007
01mar2007 28jun2007
17mar2007 01jun2007
17mar2007 31may2007
17mar2007 30jun2007
28jun2007 17mar2007
28jun2007 31mar2007
28jun2007 01mar2007
28jun2007 28feb2007
01jun2007 17mar2007
30jun2007 17mar2007
;
data lotto;
set toto;
format date_C date9. ;
date_C = date_A + Diff_A_B;
do while (datDif (date_A, date_C, '30/360') NE Diff_A_B);
if datDif (date_A, date_C, '30/360') < Diff_A_B then date_C = date_C+1;
else date_C = date_C-1;
end;
run;
Das sollte nicht sein
Hallo Herr Mangold
und alle anderen :),
Das Ergebnis ist ja höchst suspekt.
Wie kann es sein das man für den Zeitraum 17mar2007 bis 01jun2007 und 17mar2007 bis 31may2007 den selben Zeitabstand erhält (nähmlich die besagten 74 Tage? Das ergibt für mich keinen rechten Sinn.
Könnten dies durch Rundungen entstehen?
Ansonsten würde ich die problematik wie folgt lösen (Ist geschmackssache):
(Wobei ich mir die Unterschiede in meinem Code, die ich in den Fällen 4 und 5 sowie 11 beobachte, mir nicht erklären kann.)
format date_A date_B date9. ;
informat date_A date_B date9. ;
input date_A date_B;
output;
datalines;
17mar2007 28jun2007
31mar2007 28jun2007
01mar2007 28jun2007
17mar2007 01jun2007
17mar2007 31may2007
17mar2007 30jun2007
28jun2007 17mar2007
28jun2007 31mar2007
28jun2007 01mar2007
28jun2007 28feb2007
01jun2007 17mar2007
30jun2007 17mar2007
;
RUN;
data LoLo ;
format date_A date_B date_recon zwischen_recon date9. ;
SET toto;
Diff_A_B = datDif(date_A, date_B,'30/360') ;
/* Die Verschiebung auf Monatsebene ermitteln, wobei uns nur ganze
Monate interessieren
*/
month_diff_A_B = INT(Diff_A_B/30);
/* Dann schauen wir uns die restlichen Tage an */
day_rest_a_B = MOD(DIFF_A_B,30);
/* Jetzt verschieben wir erst in den richtigen Monat */
zwischen_recon = INTNX('month',date_A,month_diff_A_B,'sameday');
/* im letzten Schritt verschieben wir innerhalb des Monats um
die restlichen Tage
*/
date_recon = INTNX('DAY',zwischen_recon,day_rest_a_B,'e');
diff_check = datDif(date_A, date_recon,'30/360') ;
run ;
Ich werde nochmal wenn ich etwas mehr zeit hab das Problem detailiert zerlegen ...
Unterschied datdif und intck
Hallo,
nicht "das Ergebnis ist ja höchst suspekt", sondern
datdifundintcksind absichtlich zwei verschiedne Funktionen, siehe SAS-Online-Doku.datdifrechnet z.B. für die Banken mit 30 Tagen pro Monat und 360 Tagen pro Jahr (egal ob Schaltjahr ist oder nicht!), was ja eigentlich ziemlich falsch ist.intckrechnet absolut exakt und berücksichtigt jeden Tag und alle Tage im Jahr, inklusive Schalttagen etc pp.Gruß
Hans Kneilmann, Schäfer Shop GmbH (SSI)
Missverständnisse
Hallo,
Da haben Sie mich missverstanden. Entschuldigung hätte mich wohl klarer auf Datdiff beziehen sollen :).
Mir ist Suspekt das datdiff für 2 Abstände (17mar2007 bis 01jun2007 und 17mar2007 bis 31may2007 ) die gleiche Anzahl an Tagen (74) ermittelt.
Viele Grüße
Peter Kovacs
Ausschnitt aus dem Dataset:
Beob. date_A date_B Diff_A_B
4 17MAR2007 01JUN2007 74
5 17MAR2007 31MAY2007 74
Ahh alles klar
Bei genauerer Überlegung / Nachlesen hat sich mir das Problem mir erschlossen.
Der letzte Tag im Monat wird von datdiff vernachlässigt. Das heißt beim zurückrechnen sind die Monatsübergänge mit 31ten Tag nicht ein ein deutig. Das war mir nicht so ganz klar. Wieder was gelernt :-D
Danke Herr Kneilmann.
Gruß
Peter Kovacs
Vielleicht so ...
Ich würde auf das Problem wie folgt abbilden:
format date_A date_B date9. ;
date_A = '17mar2007'd ;
date_B = '28jun2007'd ;
diff_a_b=intck('day', date_a, ddate_b);
run ;
Dann lässt sich das Enddatum einfach berechnen:
format date_A date_B date9. ;
date_a = '17mar2007'd ;
diff_a_b= 103;
date_b = sum(date_a , diff_a_b);
run;
Datum-Rechnerei problemlos mit SAS functions
Hallo
wie immer in solchen und ähnlichen Fällen würde ich mich voll auf die
functionsaus SAS Base stützen, also keindate_b = sum(date_a , diff_a_b);(denn dass wäre mir zu sehr Assembler-ähnlich, es setzt voraus, dass das Datum in Anzahl Tagen ab X gespeichert ist), sondern mit der SAS-Base-FunktionINTNX.Also so:
format date_A date_B date9. ;
informat date_A date_B date9. ;
input date_A date_B;
diff_a_b=intck('day', date_a, date_b);
/* intck wie O.Wagner, 20. Juni 2008, 10:24 */
/* statt datDif in A.Mangold, 20. Juni 2008, 16:58 */
put "INFO: " _N_= date_A= date_B= diff_a_b=;
output;
datalines;
17mar2007 28jun2007
31mar2007 28jun2007
01mar2007 28jun2007
17mar2007 01jun2007
17mar2007 31may2007
17mar2007 30jun2007
28jun2007 17mar2007
28jun2007 31mar2007
28jun2007 01mar2007
28jun2007 28feb2007
01jun2007 17mar2007
30jun2007 17mar2007
;
data lotto;
set toto;
format date_C date9. ;
date_C = intnx('day' , date_a, diff_a_b );
/* fertig, sonst nix ... */
/* Ab hier: just for fun (zur Kontrolle) */
if date_C ne date_B then do;
put "ERROR: " _N_= date_A= date_B= date_C= diff_a_b=; STOP;
end;
else do;
put "INFO: " _N_= date_A= date_B= date_C= diff_a_b=;
end;
run;
Vorteil: Man rechnet immer richtig (s.o.: Nachteil ist, dass man beim vorwärts-rückwärts-rechnen nicht immer beim gleichen Datum landet,),
und
es wird kein Wissen über die interne Datums-Darstellung vorausgesetzt.
Gruß
Hans Kneilmann, Schäfer Shop GmbH (SSI)