Methode zum Addieren von Tagen



  • @john-0 sagte in Methode zum Addieren von Tagen:

    weil da auch alle Änderungen berücksichtigt werden z.B. Schaltsekunden. Unter UNIX/Linux ist es daher am sinnvollsten die UNIX Epoch zu nutzen, d.h. intern im Programm ausschließlich die Sekunden seit dem 1.1.1970 UTC zu verwende

    Seit sind Schaltsekunden in der Epoch enthalten? Schaltsekunden werden dort gerade nicht behandelt. Hier:

    $ date --date='@0'
    Do 1. Jan 01:00:00 CET 1970
    $ date --date="@$(((49*365 + 12)*86400))"
    Di 1. Jan 01:00:00 CET 2019
    

    Ich habe ganzzahlige Vielfache von 86400 addiert, dennoch sind die Sekunden insgesamt gleich geblieben.

    Sollen Schaltsekunden berücksichtigt werden, einfach mal https://github.com/HowardHinnant/date/wiki/Examples-and-Recipes#but-what-about-leap-seconds lesen.



  • @Kuklinski sagte in Methode zum Addieren von Tagen:

    Ja, da gebe ich Euch recht, Systemfunktionen sind dem Ganzen hier wohl vorzuziehen, aber ich mache das Ganze zu Übungszwecken um ein besseres Verständnis zu bekommmen. Und es funktioniert ja, bloß bleibt es an unbestimmten Stellen immer wieder hängen. Den Debugger habe ich schon benutzt, das Problem ist dass der Fehler erst beim 98. Durchlauf auftritt. Da bin ich alt und grau bis ich alle Durchläufe manuell durchlaufen habe.
    Gibt es eigentlich im Debugger des Visual Studio 2017 eine Möglichkeit direkt zu einem Bestimmten Durchlauf zu springen?

    ich mach das immer so:

    for ( unsigend i = 0; i < 100;++i )
    {
        if ( i == 98 )
            int k = 0; // hier Breakpoint setzen
        ...
    }
    

    Manche IDEs haben aber konditionelle Breakpoints, wo du quasi die Bedingung fürs anhalten direkt festlegen kannst.


  • Mod

    @wob sagte in Methode zum Addieren von Tagen:

    @john-0 sagte in Methode zum Addieren von Tagen:

    weil da auch alle Änderungen berücksichtigt werden z.B. Schaltsekunden. Unter UNIX/Linux ist es daher am sinnvollsten die UNIX Epoch zu nutzen, d.h. intern im Programm ausschließlich die Sekunden seit dem 1.1.1970 UTC zu verwende

    Seit sind Schaltsekunden in der Epoch enthalten? Schaltsekunden werden dort gerade nicht behandelt. Hier:

    $ date --date='@0'
    Do 1. Jan 01:00:00 CET 1970
    $ date --date="@$(((49*365 + 12)*86400))"
    Di 1. Jan 01:00:00 CET 2019
    

    Ich habe ganzzahlige Vielfache von 86400 addiert, dennoch sind die Sekunden insgesamt gleich geblieben.

    Sollen Schaltsekunden berücksichtigt werden, einfach mal https://github.com/HowardHinnant/date/wiki/Examples-and-Recipes#but-what-about-leap-seconds lesen.

    Der Witz an Schaltsekunden ist doch gerade, dass sie in dem ganzen Datumskram gar nicht vorkommen. Man braucht sie nicht zu beachten, man darf sie auch nicht beachten. Bei den Schaltsekunden hat die Welt einfach beschlossen, für eine Sekunde die Uhren anzuhalten, und so zu tun, als wäre nie etwas gewesen. Die einzige Gelegenheit, bei der man Schaltsekunden beachten muss, ist, wenn man eine eigene Atomuhr betreibt, die anderen Uhren die Zeit diktiert. Für alle anderen Uhren hat jedes Jahr exakt 86400 Sekunden.



  • @wob sagte in Methode zum Addieren von Tagen:

    Seit sind Schaltsekunden in der Epoch enthalten? Schaltsekunden werden dort gerade nicht behandelt.

    Die UNIX Epoch ist immer frei von Schaltsekunden (d.h. die Zeit in Sekunden seit dem 1.1.1970 00:00 UTC) und zählt direkt in Sekunden weiter, weil es sonst zu internen Problemen kommen könnte bis hin zum Absturz von Programmen. Ob in der bürgerlichen Zeitdarstellung die Schaltsekunden berücksichtigt werden, ist systemabhängig.



  • @john-0 sagte in Methode zum Addieren von Tagen:

    Die UNIX Epoch ist immer frei von Schaltsekunden

    Genau. Ich hatte dein vorheriges Posting nur genau andersrum verstanden.



  • @It0101 sagte in Methode zum Addieren von Tagen:

    @Kuklinski sagte in Methode zum Addieren von Tagen:

    Ja, da gebe ich Euch recht, Systemfunktionen sind dem Ganzen hier wohl vorzuziehen, aber ich mache das Ganze zu Übungszwecken um ein besseres Verständnis zu bekommmen. Und es funktioniert ja, bloß bleibt es an unbestimmten Stellen immer wieder hängen. Den Debugger habe ich schon benutzt, das Problem ist dass der Fehler erst beim 98. Durchlauf auftritt. Da bin ich alt und grau bis ich alle Durchläufe manuell durchlaufen habe.
    Gibt es eigentlich im Debugger des Visual Studio 2017 eine Möglichkeit direkt zu einem Bestimmten Durchlauf zu springen?

    ich mach das immer so:

    for ( unsigend i = 0; i < 100;++i )
    {
        if ( i == 98 )
            int k = 0; // hier Breakpoint setzen
        ...
    }
    

    Manche IDEs haben aber konditionelle Breakpoints, wo du quasi die Bedingung fürs anhalten direkt festlegen kannst.

    Ich hab das jetzt so ähnlich gemacht, danke für den Tip! Es hat sich rausgestellt dass ihm meine if Logik wohl nicht so ganz gepasst hat. 97 mal ging alles gut und beim 98. passte es ihm auf einmal nicht mehr und es gab eine Endlosschleife. Hab das ganze jetzt ein Bisschen umgeschrieben und es funktioniert hervorragend.
    Hier der code, sollte das jemand mal brauchen:

    Date & Date::operator+=(const int days)
    {
    	int rest = days;
    
    	while (rest)
    	{
    		if (month == 2)
    		{
    			if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0))
    			{
    				if (day < 29)
    				{
    					++day;
    					--rest;
    				}
    				else
    				{
    					day = 1;
    					++month;
    					--rest;
    				}
    			}
    			else
    			{
    				if (day < 28)
    				{
    					++day;
    					--rest;
    				}
    				else
    				{
    					day = 1;
    					++month;
    					--rest;
    				}
    			}
    		}
    		else if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10)
    		{
    			if (day < 31)
    			{
    				++day;
    				--rest;
    			}
    			else
    			{
    				day = 1;
    				++month;
    				--rest;
    			}
    		}
    		else if (month == 4 || month == 6 || month == 9 || month == 11)
    		{
    			if (day < 30)
    			{
    				++day;
    				--rest;
    			}
    			else
    			{
    				day = 1;
    				++month;
    				--rest;
    			}
    		}
    		else if (month == 12)
    		{
    			if (day < 31)
    			{
    				++day;
    				--rest;
    			}
    			else
    			{
    				day = 1;
    				month = 1;
    				++year;
    				--rest;
    			}
    		}
    	}
    	return *this;
    }
    


  • @Kuklinski sagte in Methode zum Addieren von Tagen:

    Hier der code, sollte das jemand mal brauchen:

    ne, den Mist braucht kein Mensch.



  • Hier mal dein Quelltext in weniger Code 😉 Habs jetzt nicht getestet, hab auch keine Ahnung, was du da treibst, es geht nur ums Prinzip.

    void doStuff( int maxday, int &day, int &rest, int &mo )
    {
        if ( day < maxday )
            ++day;
        else
        {
            day = 1;
            ++month;
        }
        --rest;
    }
    
    
    
    Date & Date::operator+=(const int days)
    {
        enum MonthType { mt30Days = 0, mt31Days, mtOther, mtDec };
        std::vector<MonthType> Months = { mt31Days, mtOther, mt31Days, mt30Days, mt31Days, mt30Days, mt31Days, mt31Days, mt30Days, mt31Days, mt30Days, mtDec };
    
        int month = 3;
        int year = 1982;
    	int rest = days;
    	while ( rest )
    	{
    		if ( Months[ month ] == mtOther )
    		{
    			if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0))
    			    doStuff( 29, day, rest, month );
    			else
                               doStuff( 28, day, rest, month );
    		}
    		else if ( Months[ month ] == mt31Days )
    		    doStuff( 31, day, rest, month );
    		else if ( Months[ month ] == mt30Days )
    		    doStuff( 30, day, rest, month );
    		else if ( Months[ month ] == mtDec )
    		{
    		    doStuff( 31, day, rest, month );
    		    if ( day >= 31 )
    		    {
    		         month = 1; // Januar
                             ++year; // Neues Jahr
            	    }
    		}
    	}
    	return *this;
    }
    


  • Ich würds nicht so machen. Der beste Tipp wurde schon genannt: Die Anzahl der Tage seit einem Referenzdatum. Da Umrechnungen nur an zwei Stellen (hin und zurück) stattfinden, sind auch Daten vor 1582 (Umstellung auf den Gregorianischen Kalender) kein Problem.
    Als Bonus hat man die Wochentagbestimmung frei Haus (seit 1.1.1 -> (days+5)%7 [1.1.1 war ein Samstag]).
    Überläufe braucht man überhaupt nicht beachten und es kann kein ungültiges Datum geben. Mit einer Zeitklasse, die intern in (Milli-) Sekunden seit 0:0:00 arbeitet, und einer Momentklasse, die beide (Datum und Zeit) einbindet, können auch beliebige Zeitpunkte und Differenzen betrachtet werden.



  • @It0101 sagte in Methode zum Addieren von Tagen:

    // [dreckiger code]
    

    Noch so ein Held. Die Bestimmung ob irgendwas ein Schaltjahr ist hat in einer Funktion zum addieren von Tagen nichts verloren.

    Und überhaupt: https://stackoverflow.com/a/11595914/3975177



  • @Swordfish sagte in Methode zum Addieren von Tagen:

    @It0101 sagte in Methode zum Addieren von Tagen:

    // [dreckiger code]
    

    Noch so ein Held. Die Bestimmung ob irgendwas ein Schaltjahr ist hat in einer Funktion zum addieren von Tagen nichts verloren.

    Und überhaupt: https://stackoverflow.com/a/11595914/3975177

    Ich hab doch gesagt, mir ist egal was er da treibt. Ich wollte nur seinen Quelltext etwas "hübscher" machen. Ich mag eben schöne Dinge 😃


  • Mod

    @yahendrik sagte in Methode zum Addieren von Tagen:

    Ich würds nicht so machen. Der beste Tipp wurde schon genannt: Die Anzahl der Tage seit einem Referenzdatum. Da Umrechnungen nur an zwei Stellen (hin und zurück) stattfinden, sind auch Daten vor 1582 (Umstellung auf den Gregorianischen Kalender) kein Problem.

    Besser noch: Man ist so gar nicht mehr auf irgendwelche Kalender festgelegt, egal ob gregorianisch, julianisch, chinesischer Mondkalender, oder nordkoreanischer Revolutionskalender. Dann hat man intern nur noch Zeitpunkte als abstraktes Konzept, ganz ohne eine Einheit. Der tatsächliche Kalander spielt dann nur bei der Interatkion mit einem Menschen die Rolle einer Darstellungsweise.



  • @Swordfish sagte in Methode zum Addieren von Tagen:

    @Kuklinski sagte in Methode zum Addieren von Tagen:

    Hier der code, sollte das jemand mal brauchen:

    ne, den Mist braucht kein Mensch.

    Dann zieh Leine und stink hier nicht rum!


  • Mod

    @Kuklinski sagte in Methode zum Addieren von Tagen:

    @Swordfish sagte in Methode zum Addieren von Tagen:

    @Kuklinski sagte in Methode zum Addieren von Tagen:

    Hier der code, sollte das jemand mal brauchen:

    ne, den Mist braucht kein Mensch.

    Dann zieh Leine und stink hier nicht rum!

    Super Einstellung. Du hast furchtbaren Code, bekommst erklärt, wieso der furchtbar ist, und wie es besser geht, und reagierst so wie hier. Hauptsache funktioniert, oder? Wenn dein Code dann in absehbarer Zeit explodiert, werden dir sicher alle furchtbar gerne helfen wollen.



  • @SeppJ sagte in Methode zum Addieren von Tagen:

    @Kuklinski sagte in Methode zum Addieren von Tagen:

    @Swordfish sagte in Methode zum Addieren von Tagen:

    @Kuklinski sagte in Methode zum Addieren von Tagen:

    Hier der code, sollte das jemand mal brauchen:

    ne, den Mist braucht kein Mensch.

    Dann zieh Leine und stink hier nicht rum!

    Super Einstellung. Du hast furchtbaren Code, bekommst erklärt, wieso der furchtbar ist, und wie es besser geht, und reagierst so wie hier. Hauptsache funktioniert, oder? Wenn dein Code dann in absehbarer Zeit explodiert, werden dir sicher alle furchtbar gerne helfen wollen.

    Mein Kommentar bezog sich auf einen unverschämten Beitrag, gegen konstruktive Kritik ist nichts einzuwenden. Ich bin immer für höfliche Kommunikation. Das muss aber auf Gegenseitigkeit beruhen!

    Was ist denn an meinem Code so furchtbar? Hat bisher niemand gesagt. Ich finde den code durchaus gut lesbar...



  • @Kuklinski Der Code ist langsam und feheranfällig.

    Stell dir vor, du möchtest 10.000 Tage addieren. Das machst du, indem du 10.000 Mal einen Tag addierst. Das klingt doch schon nach viel unnötiger Arbeit - oder etwa nicht?

    Dagegen hier:

    year_month_day d = sys_days{year(2000)/10/27} + days{98};
                                ^ 1. Ein year_month_day erstellen
                       ^ 2. in sys_days wandeln, d.h. in etwas, das Tage seit Referenzdatum zählt
                                                    ^ 3. 98 Tage addieren
    ^ 4. Ergebnis wieder in year_month_day umwandeln (zur Anzeige)
    

    Gebe zu, dass man etwas braucht, um in die std::chrono-Denkweise heineinzukommen, aber dann ist es gar nicht so schlecht.



  • Dieser Beitrag wurde gelöscht!


  • @wob sagte in Methode zum Addieren von Tagen:

    @Kuklinski Der Code ist langsam und feheranfällig.

    Stell dir vor, du möchtest 10.000 Tage addieren. Das machst du, indem du 10.000 Mal einen Tag addierst. Das klingt doch schon nach viel unnötiger Arbeit - oder etwa nicht?

    Dagegen hier:

    year_month_day d = sys_days{year(2000)/10/27} + days{98};
                                ^ 1. Ein year_month_day erstellen
                       ^ 2. in sys_days wandeln, d.h. in etwas, das Tage seit Referenzdatum zählt
                                                    ^ 3. 98 Tage addieren
    ^ 4. Ergebnis wieder in year_month_day umwandeln (zur Anzeige)
    

    Gebe zu, dass man etwas braucht, um in die std::chrono-Denkweise heineinzukommen, aber dann ist es gar nicht so schlecht.

    Ja, wie gesagt, das sehe ich auch so, der Code ist natürlich langsam und Systemfunktionen, Standartbibliotheken etc. sind da sicherlich effizienter, aber so war die Aufgabenstellung in diesem Fall, einfach um ein besseres Verständnis für das Ganze zu bekommen. Ich bin ja noch im Studium und da dürfen wir das fertige Zeug nicht benutzen. Sonst, klar, wäre das sicherlich nicht die beste Lösung, keine Frage.



  • @Kuklinski sagte in Methode zum Addieren von Tagen:

    … aber so war die Aufgabenstellung in diesem Fall …

    Wenn Du Probleme bei Übungsaufgaben hast, dann schreib das am besten gleich dazu. Dann weiß jeder, dass der „Schwachsinn“ nicht auf Deinem Mist gewachsen ist, und man kann sich die Diskussion um „best practise“ sparen.


  • Mod

    Selbst wenn man keine Systemfunktionen benutzt, wurde in diesem Thread mehrmals angesprochen, wie man Datumsangaben effizient, flexibel, und fehlerunanfällig verarbeitet: Indem man eben nicht in irgendeinem Kalendersystem arbeitet. Die Datenstruktur für einen Zeitpunkt sollte nur eine Zahl und ein impliziter Referenzzeitpunkt sein. Dann werden alle Berechnungen mit Zeitpunkten trivial (und somit effizient und fehlerunanfällig). Die Umrechnung von oder nach einem Kalendersystem sollte wirklich nur dann erfolgen, wenn eine Darstellung in einem bestimmten Kalendersystem benötigt wird (somit ist man flexibel beim Kalendersystem, effizient beim Umrechnungsaufwand, und hat diesen fehleranfälligen Teil nur einmal und kann ihn entsprechend gut testen).


Anmelden zum Antworten