Frage an C-Spezialisten - Datum/Zeitdifferenz

  • Hallo (hevo2???),


    bevor ich mich hintersinne, quäle....


    hat jemand ein Beispiel einer Routine, Funktion um folgendes festzustellen:


    ich habe 2 Werte Start und Ende mit z.B.


    y, m, d, h, min, sek (2007/06/26 14:26:52)


    und möchte wissen, ob ein beliebiger Wert dazwischen liegt:


    Start <= Prüfwert <= Ende.


    Als Anfänger in C sind die mir vorliegenden Beschreibungen (z.B. aus dem Buch C von A bis Z) die u.a.in der Headerdatei <time.h> hinterlegt sind (immer) noch ein Buch mit 7 Siegel....

  • Sag mal bitte etwas mehr, "welches C" (Standard C, C++, Visual Studio (also mit MFC), Visual Studio .NET, ...). Dann nehme ich mir meinen Anwalt und sage mehr ... ;)

  • Ok. Hintergrund der Frage: je nach System gibt es verschiedene Verpackungen für das "Problem". Also bleiben wir bei ANSI-C ...


    1.) es gibt den Datentyp time_t, welcher einfach binär die Sekunden seit dem Urknall (i.a. 1.1.1970) speichert. Der größere Wert ist immer der spätere. Hast du deine 3 Zeitpunkte in time_t konvertiert, dann kannst du sie direkt vergleichen.


    2.) wie bekommt man eine Variable vom Type time_t mit einem bestimmten Wert? Na, man nehme die Struktur "struct tm". Diese Struktur hat Felder für die einzelne Bestandteile (Tag, Monat, Jahr, Stunden, ...), welche man einfach belegen kann. Die Funktione mktime () wandelt "struct tm" in "time_t" um.


    Also:


    #include <stdio.h>
    #include <memory.h>
    #include <time.h>


    void main ()
    {
    struct tm start, end ;
    time_t tStart, tEnd, tNow ;


    /* start is the 1.1.2007 00:00:00 */
    memset (&start, 0, sizeof (start)) ;
    start.tm_mday = 1 ; start.tm_mon = 0; start.tm_year = 2007-1900 ; start.tm_hour = 0; start.tm_min = 0 ; start.tm_sec = 0; start.tm_isdst = 0 ;
    tStart = mktime (&start) ;


    /* end is the 28.2.2008 23:59:59 */
    memset (&end, 0, sizeof (end)) ;
    end.tm_mday = 28 ; end.tm_mon = 1; end.tm_year = 2008-1900 ; end.tm_hour = 23; end.tm_min = 59 ; end.tm_sec = 59; end.tm_isdst = 0 ;
    tEnd = mktime (&end) ;


    /* get "now" */
    tNow = 0 ;
    tNow = time (&tNow) ;


    /* now between start end end? */
    if ((tStart <= tNow) && (tNow <= tEnd))
    printf ("yes\n") ;


    }


    Einige Werte der Felder von tm sind komisch, weil mit C definiert (Jahr = Jahr -1900!, Monat 0..11 für Januar bis Dezember, ...).


    Noch Fragen? (Gerne :))

  • Also, erstmal herzlichen Dank.


    Mit time_t versuchte ich mich schon anzufreunden. Aber, es gibt halt so als "blutiger Anfänger" immer wieder diese Stolpersteinchen... :(


    Nun habe ich wieder was, mich damit zu beschäftigen. Wird wieder ein Weilchen dauern, obwohl... Ich versuche das mal möglichst gleich in den Compiler zu packen und anzusehen. :]



    Na gut, Du kennst ja den schönen Spruch: Kunst kommt von können, wenn mans kann, ist es keine Kunst mehr. :gap


    Äh, sehe gerade: include memory ??? Sehe ich zum ersten mal, wofür issn das?

    Einmal editiert, zuletzt von karomue ()

  • Hallo Jörg,


    da es sich nicht ziemt Spezialisten anzuzweifeln :D klingt das jetzt vielleicht etwas komisch: es läuft. Musste allerdings - wegen memset, was immer das ist, aber das versuche ich morgen rauszubringen - noch string.h nachtragen.


    Na ja, noch son schöner Spruch: glauben ist gut, wissen ist besser.


    Und nu weiß ichs ja, nochmals vielen Dank. Das in eine Prozedur zu bringen sollte mir gelingen. Und dann hoffe ich, überhaupt richtig gedacht zu haben und diese Routine das bringt, was ich mir vorstellte. Sonst muss ch die Logik meines biologischen Computers - wieder mal - überprüfen. :( :D


    ANSI, ja klar. Und die kleinen Ungereimtheiten, Komik mit Jahr, Monat mit 0 angefangen, Tag aber schon mit 1.....


    Ich hab auf dem anderen Rechner aus dem Internet eine kleine Routine "getestet":


    /* time6.c */
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    int main(void) {
    struct tm *zeit;
    time_t sekunde;
    char string[80];
    time(&sekunde);
    zeit = localtime(&sekunde);
    strftime(string, 80,
    "Es ist %H Uhr und %M Minuten (%Z) %A, %B %Y",zeit);
    printf("%s\n",string);
    return EXIT_SUCCESS;


    und zusätzlich mal (fast) alle Formatierungszeichen eingefügt, so auch %j Das sollte eigentlich


    %j Tag des Jahres (1366)


    bringen, also heute 45, brachte aber 014. Könntest Du das mal evtl kurz prüfen, Fehler in meinem Buch, Bug im LCC??

  • Warum soll am 14. der Tag des Jahres 45 sein? ?(


    45 hätte ich am 14.Februar erwartet....

    Navigation mit Google Maps über Android Auto und AAWireless im Nissan Qashqai Akari Automatik. Zusätzlich ist POIbase NAVI ein treuer Beegleiter meiner Fahrten  ;)

    Einmal editiert, zuletzt von HSVMichi ()

  • Zitat

    Original von HSVMichi
    Warum soll am 14. der Tag des Jahres 45 sein? ?(


    45 hätte ich am 14.Februar erwartet....


    Danke Michi, das war mal wieder notwendig.


    Manchmal verbeißt man sich in ein Problem und sieht den Wald vor lauter Bäumen nicht mehr....


    Dann war es wohl doch schon etwas spät gestern Nacht. Wobei ich nicht sagen möchte, dass ich meiner Zeit voraus bin... :gap

  • Prima: hier werden nicht nur die Schreibfehler gefunden.


    Ich muss memory.h includiren um memset() aufrufen zu können. Mit memset() wird die gesamte tm-Struktur mit 0 initialisiert ohne jedes Feld einzeln anfassen zu müssen.


    Ansonsten darf man bei den Zeitsachen ruhig verzweifeln, weil es da jede Menge Stolpersteine gibt:
    -) einige Routinen verwenden interne statische Puffer/Strukturen, was zu Seiteneffekten führt, wenn man es nicht weiß udn beachtet
    -) die Werte fangen mal bei 0 und mal bei 1 an
    -) mal muss man Adressen der Speicher übergeben und mal kann man auch NULL übergeben. Übergibt man die Adresse, muss der Speicher mal mit 0 initialisiert sein und mal nicht
    -) jeder beschreibt die Routinen anders
    -) ...


    Also, immer schön Übern, Lesen und nicht verzweifeln :D

  • Zitat

    Original von JSPI
    Prima: hier werden nicht nur die Schreibfehler gefunden.




    Also, immer schön Übern, Lesen und nicht verzweifeln :D



    Ja.


    Und ja, nur manchmal versucht man den Weg des geringsten Widerstandes, wie man sieht, hat es ja auch hier wieder geklappt... :] :] :]


    Übrigens hat mein Desk die main-Strucktur (+ memset) angemotzt, lief aber dann als string.h ergänzt wurde. Beim NB musste ich in int main (void) ändern.


    Man sieht, auch wenn auf beiden PC LCC gleichartig installiert und eingestellt wurde, der Stolpersteine sind mehrere.... ?(


    Und nun gäbe es noch eine Frage (bevor ich es durchprobiere): bleibt der Zeiger von memset erhalten wenn ich in eine Funktion springe, ist er also "global" oder "lokal"? Ich bin noch nicht ganz sicher, ob ich diese Auswertung in eine Schleife packe (die eigentlich schon vorhanden ist) oder in eine Funktion auslagere. Wenn ich Variable übergeben müsste - je 6 für Start, Ende und Vergleich (der nicht now ist) - das könnte evtl. nicht klappen. Erstens weiß ich nicht, wie viel Variable man denn an eine Funktion übergeben kann, dann sind 18 ein wenig viel, wenns überhaupt geht, braucht man Zeilenumbrüche im Funktionskopf, und die sind auch nicht so einfach und harmlos.


    Tja, so ein Anfänger hats schon schwer.. :(

  • Dem memset () wird per Pointer die Adresse des Speicherbereichs übergeben, welchen meset () mit dem enstprechenden Wert (hier 0) beschreiben soll. memset () merkt sich nichts. Also alles unkritisch.


    Alle anderen verwendeten (Zeit-)routinen sind auch unkritisch, solange man nicht gmtime () oder localtime () verwendet (diese arbeiten intern mit EINEM Puffer, den sie dem Nutzer liefern; wenn man den an mktime () übergibt, überschreibt mktime () den von gmtime/locatime verwendeten Puffer!).


    An eine Routine 18 Argumente zu übergeben ist unkritisch (vor allem, wenn es sich um einfache Integers handelt). Die Frage, mit 3 Strukturen zu arbeiten oder so, bringt weder vom Aspekt Speicherplatz noch CPU-Zeit etwas (an der Stelle). Es wäre reine Geschmackssache, wie man es aufschreibt. Wie du die Routine formatiert (alle Argumente in einer Zeile oder nicht), ist auch ganz deinem Geschmack überlassen.


    Übrigens gilt, dass man in C zwischen jeden Token (der Sprache) beliebig viele Whitspaces (Leeerzeichen, Zeilenumbruch, Tab, ...) einfügen darf. Also keine Furcht, mittels Zeilenumbruch mehr Leserlichkeit zu erzwingen!


    Im übrigen ist es nicht verwunderlich, das unterschiedliche Compiler oder unterschiedliche "Settings" (Warnung-Level, ANSI-C-Standard, ...) die main()-Routine unterschiedliche "haben" wollen. Da muss man sich keinen Kopf machen.

  • Hallo Jörg,


    interpretiere ich TH richtig mit techn. Hochschule? Du scheinst vom "Fach" zu sein... :]


    Vorab mal, es löppt. Ich komme so gegen 8 - 9 nochmal etwas ausführlicher.

  • TH - Thüringen ;)


    Und vom Fach: na ja. Bin eigentlich so'n trockener Mathematiker. Muss allerdings mit Softwareentwicklung mein Geld verdienen 8)

  • Zitat

    Original von JSPI
    TH - Thüringen ;)


    Und vom Fach: na ja. Bin eigentlich so'n trockener Mathematiker. Muss allerdings mit Softwareentwicklung mein Geld verdienen 8)


    Hätte ja sein können.... :] Und vom Alter her hast Du auf jeden Fall Vorteile.


    Aber jetzt zum Ergebnis:


    ein kleiner Schritt für Dich,
    ei großer für die Menschheit - äh, für mich... :D


    Spaß beiseite, ich kann jetzt mit time-Routinen - versuchen - umzugehen, Anfänge sind geschaffen.


    Es ist eingebunden und läuft - bis auf Bugs die jetzt erst zum Vorschein kommen...


    void kmlPoint (void) {
    struct tm start, ausw, end;
    time_t tStart, tAusw, tEnd;


    int i;


    memset (&start, 0, sizeof(start));
    memset (&ausw, 0, sizeof(ausw));
    memset (&end, 0, sizeof(end));


    start.tm_year = gyStart-1900;
    start.tm_mon = gmStart-1;
    start.tm_mday = gdStart;
    start.tm_hour = ghStart;
    start.tm_min = gminStart;
    start.tm_sec = gsekStart;
    tStart = mktime (&start);


    end.tm_year = gyEnd-1900;
    end.tm_mon = gmEnd-1;
    end.tm_mday = gdEnd;
    end.tm_hour = ghEnd;
    end.tm_min = gminEnd;
    end.tm_sec = gsekEnd;
    tEnd = mktime (&end);


    if (gTF_Index > 0) {


    fprintf(hGEFile,"<Folder>\r\n");
    for(i=0;i<gTF_Index;i++) {


    ausw.tm_year = gGE_TR_Point_2[i][7]-1900;
    ausw.tm_mon = gGE_TR_Point_2[i][6]-1;
    ausw.tm_mday = gGE_TR_Point_2[i][5];
    ausw.tm_hour = gGE_TR_Point_2[i][8];
    ausw.tm_min = gGE_TR_Point_2[i][9];
    ausw.tm_sec = gGE_TR_Point_2[i][10];
    tAusw = mktime (&ausw);


    fprintf(hVersFile,"tStart: %d, tAusw: %d, tEnd: %d, h: %2d, Zä: %f\r\n", //Test
    tStart,
    tAusw,
    tEnd,
    ausw.tm_hour,
    gGE_TR_Point_2[i][4]);


    if((tStart <= tAusw) && (tAusw <= tEnd)) { ....




    Sorry, die Einzüge sind beim Kopieren verschwunden...


    Nochmals meinen ganz herzlichen Dank an Dich, ich bin immer wieder erfreut, wenn hier auch Hilfe am Rande von Navi geboten wird. Wobei -


    und damit schließt sich der Kreis - dies u.a. der Erzeugung von kml-Files aus dem Loggerfile tk1 der Wintec WBT201 dient. Aber eben etwas


    anders als gewohnt. Die Trackpunkte sind Mautstellen resp. ein Rastplatz der östlichen Umfahrung Lion.