Datums berechnungen



  • Hi,

    Ich suche einen Weg wie ich zb 7 Tage vom 1.11 abziehen kann.
    ich habe das Jahr, Monat und den Tag als Integer, hätte als Ergebnis gerne sowas wie 25 und nicht -6.

    Gibt's da irgendwelche "Best practices" oder sogar eine Lib?

    Ich hoffe mir kann jemand helfen.

    Mit freundlichen Grüßen
    Lucki1000



  • Rechne zuerst den Tag im aktuellen Kalenderjahr aus, ziehe dann 7 ab, und berechne dann den neuen Monat und Tag im aktuellen Kalenderjahr.



  • Ja: std::chrono und date.h von Howard Hinnant:

    Siehe https://howardhinnant.github.io/date/date.html (bzw. https://github.com/HowardHinnant/date)

    unsinged siebenTageVorDemErstenNov = 
        static_cast<unsigned>(date::year_month_day(date::sys_days(date::year(2020)/11/1) - date::days(7)).day());
    

    Schritte:

    • date::year(2020)/11/1 ist das Startdatum.
    • Rechnen tut man damit nicht, sondern zum Addieren/Subtrahieren von Tagen/Wochen rechnet man es in sys_days um.
    • Dann kann man beliebige durations abziehen/addieren. (statt date::days(7) könnte man auch date::weeks(1) abziehen)
    • Danach wieder die sys_days in ein date::year_month_day umwandeln
    • Davon mit .day() den Tag nehmen
    • und mit static_cast in eine Zahl umwandeln

  • Mod

    Das wird mit C++20 sehr viel schöner werden, wenn den chrono-Zeitpunkten eine Kalenderschnittstelle verpasst wird. Dummerweise unterstützt das derzeit wohl noch kein Compiler (zumindest keiner auf godbolt.org). Das neue chrono: https://en.cppreference.com/w/cpp/chrono

    Prinzipiell kann chrono das alles schon, aber es hat halt derzeit kein schönes Interface, um gezielt bestimmte Kalendertage zu konstruieren. Man müsste es sich halt selber draufprogrammieren. Ein bisschen Google sagt mir, dass das schon jemand gemacht hat: https://github.com/HowardHinnant/date
    Das schaut ganz vielversprechend aus und scheint mir ungefähr (oder gar genau?) die Neuerungen an std::chrono zu implementieren. Also hier hauptsächlich die Literale und Konstruktoren für Datumsangaben.

    edit: @wob war schneller. Das Experimentieren mit godbolt hat zu viel Zeit gekostet 🙂



  • @lucki1000 ab C++20 gibt es dazu neue Klassen Calendar. Die Date Lib von Howard Hinnant (sirhe @wob) ist der Prototyp dazu.

    Rainer Grimm hat dazu auch ein paar erklärende Artikel in seinem Heise Blog geschrieben.

    Howard Hinnant erklärt die Funktion auf der CppCon 2015.



  • Vielen Dank für eure schnelle Antworten, ich werde es damit mal versuchen mein vorhaben umzusetzen.



  • @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.



  • @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.



  • @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.



  • @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.



  • @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.



  • @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.


Log in to reply