Datums berechnungen


  • Gesperrt

    @wob Warum so kompliziert? Diese Anforderung sollte man doch wohl selber hinbekommen:

    #include <stdio.h>
    
    typedef struct datum
    {
        int tag, monat, schaltjahr;
    } Datum;
    
    Datum add_days(Datum d, int days)
    {
        int i = 0;
        int tage[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 366};
        Datum d2 = d;
        int kalendertag = tage[d.monat - 1];
        kalendertag += d.tag;
        kalendertag += days;
        for (i = 1; i <= 12; i++)
        {
            if (kalendertag <= tage[i])
            {
                d2.monat = i;
                d2.tag = kalendertag - tage[i - 1];
                return d2;
            }
        }
        return d2;
    }
    
    int main()
    {
        Datum d = {1, 11, 0};
        d = add_days(d, -7);
        printf("%d. %d.\n", d.tag, d.monat);
        d = add_days(d, 7);
        printf("%d. %d.\n", d.tag, d.monat);
        d = add_days(d, 7);
        printf("%d. %d.\n", d.tag, d.monat);
        return 0;
    }
    


  • @EinNutzer0
    Und bei

    Datum d = {1, 1, 0};
    

    ?
    Man bekommt das natürlich gut selber hin, aber ganz so einfach ist es eben doch nicht.


  • Gesperrt

    @yahendrik Ja, Jahreswechsel und Schaltjahre sind blöd. 😉



  • @EinNutzer0
    Du solltest dir mal C++ angewöhnen. stdlib.h, typedef struct... und printf sind meh.



  • @EinNutzer0 sagte in Datums berechnungen:

    @wob Warum so kompliziert? Diese Anforderung sollte man doch wohl selber hinbekommen:

    Wie soll ich beurteilen, ob dein Code richtig ist? Vor allem:

    int tage[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 366};

    Wer sagt mir, dass du nicht irgendwo 1 daneben liegst? Kann dein Code auch 1000 Tage addieren? Datumsberechnung ist schwer und man kann leicht was falsch machen, wenn man es selbst versucht und keine oder nicht genügend Tests hat. Die Lösung mit date.h mag vielleicht auf den ersten Blick kompliziert aussehen, aber sie ist erstens typsicher und zweitens effizient. Und einfach zu lesen, wenn man sich einmal daran gewöhnt hat.

    Und nochwas: ein Datum wird nicht durch int tag, monat, schaltjahr; charakterisiert, sondern durch Tag, Monat und Jahr. Dein typedef struct datum repräsentiert also gar kein Datum. (und wir sind hier im C++-Unterforum, da riecht jedes typedef struct schon einmal nach C ohne ++)
    Mit date::year(2020) / 11 / 1 steht außerdem eine gut lesbare Variante direkt im Code.



  • @EinNutzer0 sagte in Datums berechnungen:

    @wob Warum so kompliziert? Diese Anforderung sollte man doch wohl selber hinbekommen:

    Nicht wirklich den Code angesehen, aber garantiert zumindest unvollständig. Datumsberechnung ist ein ziemliches "Rabbit Hole", da sollten wir froh sein, wenn wir auf sowas wie std::chrono oder andere Bibliotheken zurückgreifen können. Ich hätte da keinen Bock drauf, sowas korrekt umzusetzen.


  • Gesperrt

    @wob Ja, aber du hast dich auch nicht an die Frage des TEs gehalten. Nur der Monat und Tag sind gegeben, nicht aber das Jahr. Wir könnten davon ausgehen, dass es sich nicht um ein Schaltjahr handelt. Eine Umrechnung in einen exakten Zeitpunkt wird mit deiner Vorgehensweise also schwierig und ist auch nicht verlangt.


  • Gesperrt

    @DocShoe sagte in Datums berechnungen:

    @EinNutzer0
    Du solltest dir mal C++ angewöhnen. stdlib.h, typedef struct... und printf sind meh.

    Ja sorry... Da mir das aber zu kompliziert ist, da die Fragen nach Jahreswechseln und Schaltjahren eigentlich noch offen sind, kann ich zurzeit keine richtige (C++)Lösung anbieten. 😉

    Wenn der TE schreiben würde, jedes Datum liegt innerhalb desselben Jahres und es geht nicht um ein Schaltjahr... dann wäre es nicht so kompliziert.



  • @EinNutzer0 sagte in Datums berechnungen:

    @DocShoe sagte in Datums berechnungen:

    @EinNutzer0
    Du solltest dir mal C++ angewöhnen. stdlib.h, typedef struct... und printf sind meh.

    Ja sorry... Da mir das aber zu kompliziert ist, da die Fragen nach Jahreswechseln und Schaltjahren eigentlich noch offen sind, kann ich zurzeit keine richtige (C++)Lösung anbieten. 😉

    Dann poste doch erst, wenn du eine funktionsfähige Lösung hast. Irgendwas zu posten, nur um Erster zu sein, hilft keinem.

    @wob
    Die date-Bibliothek von Hinnant findest du gut und intuitiv? Ich halte die für völlig overengineered... und die Operatorüberladung sieht auch nur ähnlich aus wie Datumsangaben, für mich sieht das so aus wie gewollt und nicht gekonnt. Meine bisherigen Erfahrung damit waren so umständlich, dass ich mich echt gefragt habe, ob das alles ernst gemeint ist.


  • Gesperrt

    @DocShoe sagte in Datums berechnungen:

    @EinNutzer0 sagte in Datums berechnungen:

    @DocShoe sagte in Datums berechnungen:

    @EinNutzer0
    Du solltest dir mal C++ angewöhnen. stdlib.h, typedef struct... und printf sind meh.

    Ja sorry... Da mir das aber zu kompliziert ist, da die Fragen nach Jahreswechseln und Schaltjahren eigentlich noch offen sind, kann ich zurzeit keine richtige (C++)Lösung anbieten. 😉

    Dann poste doch erst, wenn du eine funktionsfähige Lösung hast. Irgendwas zu posten, nur um Erster zu sein, hilft keinem.

    Also... meine Lösung ist funktionsfähig, wenn man ein paar Einschränkungen voraussetzt... sonst hätte ich sie nicht gepostet. Allerdings hab ich die Tage mit dem Windows-Taschenrechner berechnet, es wäre also möglich, dass ich mich bei tage doch um +-1 vertan hab.



  • Wenn der TE schreiben würde, jedes Datum liegt innerhalb desselben Jahres und es geht nicht um ein Schaltjahr... dann wäre es nicht so kompliziert.

    Das Jahr hab ich natürlich auch.


  • Gesperrt

    @lucki1000 sagte in Datums berechnungen:

    Das Jahr hab ich natürlich auch.

    Dann nimm die Lösung von @wob und berechne einen genauen Zeitpunkt - das ist robuster.



  • @EinNutzer0
    Ok Danke



  • @EinNutzer0 sagte in Datums berechnungen:

    @DocShoe sagte in Datums berechnungen:

    @EinNutzer0 sagte in Datums berechnungen:

    @DocShoe sagte in Datums berechnungen:

    @EinNutzer0
    Du solltest dir mal C++ angewöhnen. stdlib.h, typedef struct... und printf sind meh.

    Ja sorry... Da mir das aber zu kompliziert ist, da die Fragen nach Jahreswechseln und Schaltjahren eigentlich noch offen sind, kann ich zurzeit keine richtige (C++)Lösung anbieten. 😉

    Dann poste doch erst, wenn du eine funktionsfähige Lösung hast. Irgendwas zu posten, nur um Erster zu sein, hilft keinem.

    Also... meine Lösung ist funktionsfähig, wenn man ein paar Einschränkungen voraussetzt... sonst hätte ich sie nicht gepostet. Allerdings hab ich die Tage mit dem Windows-Taschenrechner berechnet, es wäre also möglich, dass ich mich bei tage doch um +-1 vertan hab.

    Das nennst du funktionsfähig? Tut mir leid, wenn ich dir da an den Karren fahren muss, aber ne. Die Einschränkungen sind so groß, dass das praktisch nicht zu gebrauchen ist.


  • Gesperrt

    @DocShoe sagte in Datums berechnungen:

    Das nennst du funktionsfähig? Tut mir leid, wenn ich dir da an den Karren fahren muss, aber ne. Die Einschränkungen sind so groß, dass das praktisch nicht zu gebrauchen ist.

    Wie gesagt, beide Zeitpunkte müssen nur innerhalb desselben Jahres liegen und es darf sich nicht um ein Schaltjahr handeln. Andernfalls ist das Ergebnis undefiniert.



  • @DocShoe sagte in Datums berechnungen:

    Die date-Bibliothek von Hinnant findest du gut und intuitiv?

    Intuitiv: naja. Man muss sich schon daran gewöhnen. Overengineert: definitiv! Für 99% der Fälle möchte ich eine einfache Klasse ohne Templates, aber mit vielen nützlichen Memberfunktionen haben.

    Mich nervt, dass ich mit .day() usw. immer herumcasten muss, um wieder einen int herauszubekommen. Deswegen habe ich einen eigenen Wrapper um die date.h, die die Typsicherheit etwas zurücknimmt und die Klassen damit für mich benutzbarer macht. Auch würde ich gerne eine Duration auf ein Datum addieren können. Deswegen hat mein Wrapper auch eine Funktion addDays(int n). So, wie es jetzt ist, muss man umwandeln. Ist sicher gemacht, damit man explizit sieht, wo Umwandlung stattfindet und wo man besser effizient addieren könnte. Aber es nervt schon ein wenig.

    Ich finde den ganzen Krempel mit den vielen Clocks überflüssig. Wird sicher jemand brauchen - ich nicht. Und klar, die verschiedenen Zeit-Granularitäten mit den ratios gibt es auch noch. Wobei das schon sinnvoll ist, denn manch einer wird sicher ns-Präzision brauchen und man anderer wird mit Tagesgenauigkeit zufrieden sein.

    Diese date::*-Klassen sind doch schon ein Schritt, std::chrono benutzbar zu machen.


  • Mod

    Das scheinbare Overengineering liegt in der Natur der Sache. Denn das Thema selbst ist kompliziert, viel komplizierter als man zunächst denkt. Einerseits weil das System an sich schon semi-kompliziert ist. Andererseits weil Datumsangaben eine solch durchdringend wichtige Rolle im menschlichem Zusammenleben ausmachen, dass die Komplexität menschlicher Interaktion in das Thema überschwappt.

    Wenn man da naiv dran geht, kommt so etwas wie bei EinNutzer0 heraus. Wenn man etwas weniger naiv dran geht, kommt so etwas heraus, wie die native Kalenderunterstützung in vielen Programmiersprachen. Also Datumsangaben, und Deltas (in Tagen, Stunden, etc.) dazwischen, die für sich genommen auch korrekt funktionieren. Das ist dann die korrekte Umsetzung der technischen semi-komplizierten Aspekte, ohne die menschlichen Interaktionen.

    Aber da hört es ja in der Praxis nicht auf, denn dort braucht man oft solche Dinge wie "plus ein Monat" (klingt einfach, aber was heißt das genau?), "erster Montag des Monats", "wie vielte Woche des Jahres" (an welchem Tag fängt die Woche an? Unterstützen wir lieber mehrere…), "wie viele Monate zwischen diesen beiden Datumsangaben?", zig verschiedene Eingabeformate, Feiertage (Ortsabhängig! Veränderlich!), Zeitzonen. Und von nicht-gregorianischen Kalendersystemen will ich gar nicht erst anfangen. Und dann kommt man halt bei den vermeintlich overengineerten Zusatzbibliotheken für Datumsverarbeitung an, die es dann auch für jede praxisrelevante Programmiersprache gibt.

    PS: Man sieht schön, wie leicht man das Thema unterschätzt, denn ich habe diesen Beitrag bestimmt 5x editiert, weil mir immer weitere Verkomplizierungen eingefallen sind. Allen davon bin ich im Berfufsleben schon begegnet.


  • Gesperrt

    @SeppJ Richtig interessant wird es doch erst bei der Miteinbeziehung von Schaltjahren, Schaltsekunden und Sommer- und Winterzeit im gregorianischen Kalender. 😉 Beispielweise gibt es in einem Vertrag eine stunden- oder minutengenaue Abrechnung. Hans Müller hat einen Monatsvertrag am 5.6.2017 um 15:59 Uhr geschlossen, am 7.8.2019 um 23:20 Uhr kündigt er zum nächstmöglichen Zeitpunkt und 60,5 Stunden später gelangt diese in den Kenntnisbereich des Vertragspartners - der nicht genutzte Zeitraum soll ihm erstattet werden. Los, fang an zu rechnen. 😉



  • @EinNutzer0 sagte in Datums berechnungen:

    kündigt er zum nächstmöglichen Zeitpunkt und 60,5 Stunden später gelangt diese in den Kenntnisbereich des Vertragspartners - der nicht genutzte Zeitraum soll ihm erstattet werden. Los, fang an zu rechnen.

    Dazu müsste ich erst einmal deinen Gedankengang verstehen. Und: was ist ein "Monatsvertrag"? Wie funktioniert dieser bei kürzeren Monaten? Deswegen ist Monat auch keine vordefinierte duration.

    Rechne einfach alles in UTC. Du brauchst die Umwandlung von Lokalzeit nach UTC bei der Eingabe und zurück bei der Ausgabe.

    Ansonsten kann chrono auch problemlos mit Studen und Minuten etc. umgehen. Und für Zeitzonen guckst du hier: https://howardhinnant.github.io/date/tz.html


  • Gesperrt

    Mein Beispiel war nicht vollständig. Ich wollte damit nur verdeutlichen, dass es sehr schnell sehr kompliziert werden könnte, wenn man wirklich alles selber machen will, und es deshalb doch ratsam ist, auf bestehende Lösungen zurückzugreifen, wie ihr schon richtig gesagt habt.


Anmelden zum Antworten