Alter in Tagen berechnen



  • DAnke erstmal für den Tipp mit den Headern.
    Ich echt wird es eine Routine für c++ werden, aber da es eigentlich aus dem ansi-c stammt, dacht ich, hier richtig zu sein.

    Mein Problem ist nicht die Reihenfolge der Parameter übergabe ( vom 16. minus 1. ergibt es richtig 10Tage, vom 1. minus 16. MINUS 10 Tage. damit könnt ich leben, ( oder es auch richtig machen ) aber.
    Wie Du siehst, habe ich mehrere AUfrufe der routine aus main gestartet, und ich bekomme nur beim ersten AUfruf ein "richtiges" ergebnis. alle folgenden Aufrufe ergeben 0-Tage.
    gebe ich es über printf aus, kommt die Meldung, daß der erste Wert nan sei.
    - mit den Werten alt="20030601"; neu= "20030621"; klappt es,
    - setze ich neu= "20030611"; gibt es 0.
    - mit alt="20040101";neu= "20040401"; ( Schaltjahr !) ergibt 91
    (stimmt laut Kalender, wenn der 1.4.04 nicht mitgerechnet wird!)
    - mit alt="20030101";neu= "20030401"; ( kein Schaltjahr !) ergibt 90

    - sobald ich die beiden letzen nacheinander aus main aufrufe, hat der zweite wert wieder 0! 😕

    Ansonsten hab ich die #includes wie folgt geändert
    #include <vector>
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <iomanip>

    // stecken die nächasten drei in einer ohne .h ?
    #include <stdlib.h>
    #include <stdio.h>
    #include <time.h>

    Hanns

    p.s.: ich muss den speicher doch am Ende der Funktion nicht frei geben? . die beiden "zeit*" werden coh nur innerhalb der routine verwendet, und bei Ende freigegeben ??

    [ Dieser Beitrag wurde am 19.06.2003 um 23:02 Uhr von ^Hanns editiert. ]



  • Hi

    ich bin unter linux. Fenster o.ä dinge brauche ich nicht, da das ganze eine HTML-Seite wird.

    @^Hanns

    Nun die klasse hat nichts mit fenstern zu tun. Ich sagt lediglich, dass ich mich an der Funktionalität von CTime orientiert hab. Intern ist das auch nur n time_t. Aber naja.

    🙂



  • Nun die klasse hat nichts mit fenstern zu tun. Ich sagt lediglich, dass ich mich an der Funktionalität von CTime orientiert hab. Intern ist das auch nur n time_t. Aber naja.

    Könntest Du denn Deine Routine mal mit meinen Werten versuchen. Siehe meine Nachrichten von eben ( an entelche)
    Hanns



  • HI

    jepp, probier ich gleich ma aus. Poste dann morgen das Ergebnis.



  • Nachtrag:

    ich habe die Reihen folge der ersten beiden Aufrufe in MAIN geändert:
    Es wird immer nur der erste Aufruf korrekt abgehandelt !!!!!
    😞



  • Ich habe etwas gefunden, obwohl ich mir nciht wrklären kann , warum es so ist.

    ein Blick in time.h zeigte, daß es ja auch sec/min/std gibt
    (Frage, was bedeutet DST in der Structur ???
    ich habe also für beide struct diese werte = 0 gesetzt.

    zeitAlt->tm_year = jahrAlt - 1900;
    zeitAlt->tm_mon  = monatAlt  - 1; // oder +1 ?
    zeitAlt->tm_mday = tagAlt;
    zeitAlt->tm_sec =  0;               /* Seconds.     [0-60] (1 leap second) */
    zeitAlt->tm_min =  0;               /* Minutes.     [0-59] */
    zeitAlt->tm_hour = 0;               /* Hours.       [0-23] */
    

    Dies bracht schon mal für die Aufrufe 2 ff Secunden-Werte (mktime) ungleich 0
    Allerdings als double.

    2.) der Rückgabewert wurde in (int) geändert, und ein gerundeter wert zurückgegeben

    return (int) (( tage *10 +.5)/10);
    

    3.) die ergebnisse:
    a)
    1.1.2003 --- 1.4.2003
    SekAlt 1041375600 SekNeu 1049151600
    Alter in Tagen ( 20030101 - 20030401 ) ist 90

    b)
    1.1.2003 --- 1.4.2003
    SekAlt 1041375600 SekNeu 1049151600
    Alter in Tagen ( 20030101 - 20030401 ) ist 90

    c)
    1.1.2003 --- 1.4.2003
    SekAlt 1041375600 SekNeu 1049148000
    Alter in Tagen ( 20030101 - 20030401 ) ist 90

    d)
    1.1.2004 --- 1.4.2004
    SekAlt 1072911600 SekNeu 1080770400
    Alter in Tagen ( 20040101 - 20040401 ) ist 91

    Merkwürdig ist nur daß der Wert SekNeu - bei gleichen Eingangsdaten - in c) von denen in a) und b) abweicht.

    Wieso kalppt es, wenn man sec/min/h explizit auf 0 setzt ?
    Ich kann mir nur erklären, daß der g++ merkt, daß die routine mehrfach aufgerucfen wird, und deshalb die structur alloziert lässt ???

    ich arbeite unter Suse 8.0 mit g++.
    Könnt ihr mal auf anderen Systemen den gleichen Test durchführen ?
    ( ! ich habe die Datumsstring zuletzt gegenüber den in meinem Code-Posting geändert !)

    Gruß Hanns 😕



  • Hi

    DST ist für die Beschreibung von Zeitzonen also +-Stunden von lokaler Zeit.



  • damit du alle felder der struktur tm* zeitAlt
    auf null setzt mach ein memset( zeitAlt, 0, sizeof( *zeitAlt ) ).

    // jetzt Zeitstruktur bilden, und mit dem ersten Wert auffüllen
    struct tm *zeitAlt;
    zeitAlt = (struct tm *) malloc ( sizeof (struct tm ) );
    
    memset( zeitAlt, 0, sizeof( *zeitAlt ) );
    
    // hier musst du evtl. ein bisshen rumspielen
    zeitAlt->tm_year = jahrAlt - 1900;
    zeitAlt->tm_mon  = monatAlt  - 1; // oder +1 ?
    zeitAlt->tm_mday = tagAlt;
    
     printf( "Structur alt : %i.%i.%i\n",zeitAlt->tm_year,zeitAlt->tm_mon,zeitAlt->tm_mday);
    


  • DAnke für den Hinweis,
    aber schau Dir doch bitte mal die Unterschiedliechen ergebnisse für 3 x gleich Parameter an !
    Wie kann das sein ????

    Hanns



  • entelechie: den rückgabewert von malloc castet man nicht. 😡



  • HI

    @helm

    Ich caste den immer, es gibt auch compiler die dich anmeckern wenn du es nicht machst. malloc gibt *void zurück,und wenn ich es einem char* zuweisen will, caste ichs drauf. Was soll daran falsch sein?



  • wurde hier schon tausend mal diskutiert. will ich nicht nochmal machen.



  • Hi

    Kann ja sein hab ich noch nich mitbekommen. Würd gerne wissen was daran falsch ist. Man lernt ja nie aus. Vielleicht haste ja n link auf den Thread!? 😉





  • Noch besser währe, wenn du dir mal überlegst wie man das ganze mal ohne time etc von Hand aufbaut.
    Hab selber sowas damals noch in Q-Basic geschrieben.
    Fördert die Logik die dahinter steckt. 😉



  • Hi

    thx @helm



  • Hey jungs, darf ich Euch mal auf das eigentliche Problem hinweisen ?

    1. Es sollte das ALter in Tagen berechnet werden.
    2. wir haben die struct time dazu verwendet
    3. wenn die struct vor Verwendung nicht in einen definierte Zustand versetzt wird ( am einfachsten memeset() ) gibt es unvorhersehbare Ergebnisse.

    Dann hat sich eine weiteres Problem -und das ist noch ungklärt- ergeben.

    4.) rufe ich die Funktion mehrmals hintereinande mit den gleichen Werten auf, liefert die Umwandlung in Uhren-Ticks unterschiedliche Werte
    😡 😕 😃

    Wieso ? DIe Anzahl sekunden ab 1.1.1970 bis heute ( 0Uhr/0Minuten/0Sekunden) sind doch immer identisch, egal wie oft ich sie bestimme ? oder liege ich da falsch?

    Ich compilier mit dem g++ unter Linux.
    hier noch mal der Testcode in der aktuellen form

    /***********************************************
    * tage.cc
    * berechnen des Alters in Tagen
    * parm 1 string datum_Al, string datum_Neu
    ************************************************
    */
    
    #include <vector>
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <iomanip>
    #include <stdlib.h>
    #include <stdio.h>
    #include <time.h>
    
    int AlterInTagen ( string datum_Alt, string datum_Neu ) {
    
    // datum_x = "JJJJMMTT"  wird nicht geprüft !!!!
    // und in Tag/Monat/Jahr umwandeln
    int jahrAlt,jahrNeu,monatAlt,monatNeu, tagAlt,tagNeu;
    jahrAlt = atoi (datum_Alt.substr(0,4).c_str() );
    jahrNeu = atoi (datum_Neu.substr(0,4).c_str() );
    
    monatAlt  = atoi (datum_Alt.substr(4,2).c_str() );
    monatNeu = atoi (datum_Neu.substr(4,2).c_str() );
    
    tagAlt  = atoi (datum_Alt.substr(6,2).c_str() );
    tagNeu = atoi (datum_Neu.substr(6,2).c_str() );
    
    cout <<  tagAlt << "." <<  monatAlt << "." << jahrAlt << "  ---  " << tagNeu << "." << monatNeu << "." <<  jahrNeu << endl;;
    //  printf( "%i.%i.%i -- %i.%i.%i\n", tagAlt, monatAlt,jahrAlt, tagNeu,monatNeu , jahrNeu);
    
    // jetzt Zeitstruktur bilden, und mit dem ersten Wert auffüllen
    struct tm *zeitAlt;
    zeitAlt = (struct tm *) malloc ( sizeof (struct tm ) );
    if ( zeitAlt == NULL ) {
            cout << "Fehler bei malloc() zeitAlt !" << endl;
            return 0;
    }
    
    // hier musst du evtl. ein bisshen rumspielen
    zeitAlt->tm_year = jahrAlt - 1900;
    zeitAlt->tm_mon  = monatAlt  - 1; // oder +1 ?
    zeitAlt->tm_mday = tagAlt;
    zeitAlt->tm_sec =  0;               /* Seconds.     [0-60] (1 leap second) */
    zeitAlt->tm_min =  0;               /* Minutes.     [0-59] */
    zeitAlt->tm_hour = 0;               /* Hours.       [0-23] */
    
     // printf( "Structur alt : %i.%i.%i\n",zeitAlt->tm_year,zeitAlt->tm_mon,zeitAlt->tm_mday);
     cout << "Structur alt :" << zeitAlt->tm_year << "-" << zeitAlt->tm_mon<< "- " << zeitAlt->tm_mday << endl;
    
    // jetzt Zeitstruktur bilden, und mit dem zweiten Wert auffüllen
    struct tm *zeitNeu;
    zeitNeu = (struct tm *) malloc ( sizeof (struct tm ) );
    if ( zeitNeu == NULL ) {
            cout << "Fehler bei malloc() zeitNeu !" << endl;
            return 0;
    }
    // hier musst du evtl. ein bisshen rumspielen
    zeitNeu->tm_sec =  0;               /* Seconds.     [0-60] (1 leap second) */
    zeitNeu->tm_min =  0;               /* Minutes.     [0-59] */
    zeitNeu->tm_hour = 0;               /* Hours.       [0-23] */
    zeitNeu->tm_mday = tagNeu;
    zeitNeu->tm_mon  = monatNeu - 1; // oder +1 ?
    zeitNeu->tm_year = jahrNeu - 1900;
    // zeitNeu->tm_wday =                  /* Day of week. [0-6] */
    // zeitNeu->tm_yday =                  /* Days in year.[0-365] */
    // zeitNeu->tm_isdst =                 /* DST.         [-1/0/1]*/
    
    //  printf( "Structur neu : %i.%i.%i\n",zeitNeu->tm_year,zeitNeu->tm_mon,zeitNeu->tm_mday);
     cout << "Structur neu :" << zeitNeu->tm_year << "-" << zeitNeu->tm_mon<< "- " << zeitNeu->tm_mday << endl;
    
    // zeit in sekunden seit dem 1.1.1970 umwandeln
    time_t zeitInSAlt = mktime( zeitAlt);
    time_t zeitInSNeu = mktime( zeitNeu );
    cout << "SekAlt " << zeitInSAlt << "  SekNeu " << zeitInSNeu << endl;
    
    // differenz in sekunden berechnen
    double diffSekunden = difftime(  zeitInSNeu ,zeitInSAlt);
    double tage = diffSekunden / (3600 * 24);
    free ( zeitNeu);
    free( zeitAlt);
    return ((int) ( tage *10 +.5))/10;
    }
    
    int main () {
    string alt,neu;
    alt="20030101";
    neu= "20030102";
    cout << "Alter in Tagen ( " << alt << " - " << neu << " ) ist " << AlterInTagen( alt, neu )<< endl;
    neu= "20030401";
    cout << "Alter in Tagen ( " << alt << " - " << neu << " ) ist " << AlterInTagen( alt, neu )<< endl;
    // *************KEIN SchaltJahr*********************
    alt="20030101";
    neu= "20030401";
    cout << "Alter in Tagen ( " << alt << " - " << neu << " ) ist " << AlterInTagen( alt, neu )<< endl;
    
    // *****************SchaltJahr****
    alt="20040101";
    neu= "20040401";
    cout << "Alter in Tagen ( " << alt << " - " << neu << " ) ist " << AlterInTagen( alt, neu )<< endl;
    }
    

    Hanns

    p.s. Frank, hatt ich auch schon überlegt, aber die Zeit: hättest Du denn den Basic -code noch zum verschenken ?



  • Hab den Code sogar noch in c++ noch gehabt.Ist allerdings auch umständlich gelöst(Tage werden einzeln gezählt ...).
    Müsste mir mal ne schnellere Lösung einfallen lassen.
    Die Separatorfunktion müsstest du, wenn du keine Trennzeichen im Datum hast eben mit substr ersetzen.

    #include <conio.h>
    #include <iostream.h>
    //Funktion Separator dient zum Auslesen der Tage,Monate,Jahre aus dem string
    string Separator(string sSourceText,string sSeparator,int iPos);
    int Anzahltage(string Anfangsdatum,string Enddatum);
    void main()
    {
       string anfang,ende;
       cout << "Anfangsdatum(tt.mm.jjjj):";
       cin >> anfang;
       cout << "Enddatum(tt.mm.jjjj):";
       cin >> ende;
       cout << "\nDas sind " << Anzahltage(anfang,ende) << " Tage.";
       getch();
    }
    int Anzahltage(string Anfangsdatum,string Enddatum)
    {
       int idatum[2][3],ianztag=0,imon[12]={31,28,31,30,31,30,31,31,30,31,30,31};
       string sdatum[2]={Anfangsdatum,Enddatum};
       //string in Integerarray übernehmen
       for(int i=0;i<2;i++)
       {
          for(int j=0;j<3;j++)
          {
             idatum[i][j]=atoi(Separator(sdatum[i],".",j+1).c_str());
          }
       }
       //Solange wie Enddatum ungleich Anfangsdatum
       while(idatum[0][0]!=idatum[1][0]||idatum[0][1]!=idatum[1][1]||idatum[0][2]!=idatum[1][2])
       {
          ianztag++;//Zähler Tage
          idatum[1][0]--;//Enddatum Tage runterzählen
          if(!idatum[1][0])// Wenn Tag < 1
          {
             idatum[1][1]--;// Monat runterzählen
             if(!idatum[1][1])// Wenn Monat < 1
             {
                idatum[1][1]=12; //Monat=12
                idatum[1][2]--;  //Jahr runterzählen
             }
             idatum[1][0]=imon[(idatum[1][1]-1)];// Tage des Vormonats übernehmen
             //Wenn Schaltjahr Februar 29 Tage
             if(idatum[1][1]==2)if((idatum[1][2]%4==0&&idatum[1][2]%100!=0)||idatum[1][2]%400==0)idatum[1][0]++;
          }
       }
       return ianztag;//Anzahl Tage zurück
    }
    string Separator(string sSourceText,string sSeparator,int iPos)
    {
       int x;
       while(iPos--) x=1+sSourceText.find(sSeparator.c_str(),x);
       return sSourceText.substr(x,sSourceText.find(sSeparator.c_str(),x)-x);
    }
    

Anmelden zum Antworten