Datum Problem

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 ;

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.

data toto ;
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.)

data toto ;
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 datdif und intck sind absichtlich zwei verschiedne Funktionen, siehe SAS-Online-Doku.

datdif rechnet 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.

intck rechnet 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:

data toto;
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:

data toto2;
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 functions aus SAS Base stützen, also kein date_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-Funktion INTNX.
Also so:

data toto ;
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)