Datums berechnungen
-
@EinNutzer0 sagte in Datums berechnungen:
@Swordfish https://github.com/HowardHinnant/date ist doch eine zusätzliche, externe Lib... KISS-Prinzip.
Der Cmake Code zum einbinden der lib umfasst 5 Zeilen mit ordentlicher Formattierung. Das erscheint mir etwas simpler als den Code selbst zu schreiben
Also warum nochmal sich selbst den Kopf zerbrechen, wenn es auch einfacher geht?
-
@DocShoe sagte in Datums berechnungen:
Für eine vernünftige Ausgabe überlädt man std::ostream& operator<<( std::ostream& ) und exponiert keine Klasseninterna.
Oder man hätte eine Funktion
getCtime
, die einenstring
zurückgibt, imho. Ja ich hatte mir schon gedacht, dassreturn &my_time;
problematisch ist...
-
@Leon0402 sagte in Datums berechnungen:
Der Cmake Code zum einbinden der lib umfasst 5 Zeilen mit ordentlicher Formattierung. Das erscheint mir etwas simpler als den Code selbst zu schreiben
So viel? Die date.h ist ein Header, der von nichts abhängt. Da brauchst du gar nichts weiter zu machen. Einfach Header #includen und fertig.
Ich finde die Lösung von @EinNutzer0 wegen der Jahresproblematik recht unbrauchbar. Sie verfehlt schon einmal das Ziel, sinnvoll allgemein brauchbar zu sein. Wofür soll ich das sinnvoll einsetzen außer für den einzigen Zweck, einem Datum des aktuellen Jahres Tage zu addieren? Der Einsatzzweck wird unnötig eingeschränkt -> schlechtes Design. Und Typsicherheit? Warum (day, month) und nicht (month, day)? Man muss es nachschauen und kann es falsch machen. So nervig das Casten in date.h/chrono manchmal ist, man kann sich jedenfalls immer sicher sein, dass das richtige passiert und man keine Parameter vertauscht hat.
-
Hier nochmal, hoffentlich ohne
UB
:#include <iostream> #include <string> #include <ctime> class MyDate { public: MyDate(int day, int month) { time_t tt = time(0); tm *tp = localtime(&tt); tp->tm_mday = day; tp->tm_mon = month - 1; tp->tm_sec = 0; tp->tm_min = 0; tp->tm_hour = 0; my_time = mktime(tp); } MyDate addDays(int days) { time_t tt = my_time; tt += (days * 86400); return MyDate(tt); } std::string toString() { return ctime(&my_time); } private: time_t my_time; MyDate(time_t tt) : my_time{tt} {}; }; int main() { std::cout << MyDate(1, 11).addDays(-7).addDays(14).addDays(-14).toString() << "!\n"; // Sun Oct 25 01:00:00 2020 std::cout << MyDate(29, 3).addDays(-2).toString() << "!\n"; // Fri Mar 27 00:00:00 2020 }
Wofür soll ich das sinnvoll einsetzen außer für den einzigen Zweck, einem Datum des aktuellen Jahres Tage zu addieren?
Weil eigentlich danach gefragt wurde. Aber im Produktivsystem würde ich das eigentlich auch nicht einsetzen wollen...
-
@EinNutzer0 sagte in Datums berechnungen:
Weil eigentlich danach gefragt wurde.
Ja?
@lucki1000 sagte in Datums berechnungen:
Gibt's da irgendwelche "Best practices" oder sogar eine Lib?
-
-
@EinNutzer0 sagte in Datums berechnungen:
@manni66
@lucki1000 sagte in Datums berechnungen:
wie ich zb 7 Tage vom 1.11 abziehen kann
Ja, du kannst sogar die Frage nicht finden.
-
@manni66 Nö, es ist ein ganz eindeutiges Beispiel gewählt worden. Ich interpretiere 1.11. als 1.11.2020 und nicht als 1.11.1900.
-
@DocShoe sagte in Datums berechnungen:
@EinNutzer0
Die ist beimctime
Aufruf schon kaputt, weil du ein temporary zurückgibst. Und da das temporary weder an eine lokale Variable zugewiesen wird noch deren Lebensdauer durch Bindung an eine const-Referenz verlängert wird erzeugt derctime
Aufruf UB, weil das Temporary da schon wieder zerstört wurde.Kannst du das bitte genauer erklären? Lebt das Temporary nicht auf jeden Fall so lange, bis der äußere Aufruf von ctime abgeschlossen ist?
siehe https://en.cppreference.com/w/cpp/language/lifetime
All temporary objects are destroyed as the last step in evaluating the full-expression that (lexically) contains the point where they were created, and if multiple temporary objects were created, they are destroyed in the order opposite to the order of creation. This is true even if that evaluation ends in throwing an exception.
-
@wob sagte in Datums berechnungen:
So viel? Die date.h ist ein Header, der von nichts abhängt. Da brauchst du gar nichts weiter zu machen. Einfach Header #includen und fertig.
Ja, man kann natürlich auch die lib reinkopieren. Aber das finde ich nicht die beste Art, eine Lib einzubinden. Man sieht nicht, welche Version der lib man verwendet und muss jedes mal die header austauschen, wenn man die version updaten will.
-
@EinNutzer0 sagte in Datums berechnungen:
Hier bitte, fluent:
MyDate addDays(int days) { // ... return MyDate(tt); }
Mit "fluent" hat das aber nichts zu tun, da du jedesmal ein neues Objekt erzeugst.
So wäre es richtiger:MyDate& addDays(int days) { my_time += days * 86400; return *this; }
PS: Und eine Konstante (e.g.
SecondsPerDay
) für das Literal wäre auch angebrachter.
-
-
@EinNutzer0 sagte in Datums berechnungen:
Wie lange wäre bei
std::cout << ctime(MyDate(1, 11).addDays(365).getTimePointer()) << "!\n";
eigentlich die Lebensdauer der Klasse MyDate?
Wie sieht das denn aus wenn Du den Funktionsaufruf ausschreibst statt dem Operator
<<
? Kannst Du Dir die Frage dann selbst beantworten?
-
@wob sagte in Datums berechnungen:
@DocShoe sagte in Datums berechnungen:
@EinNutzer0
Die ist beimctime
Aufruf schon kaputt, weil du ein temporary zurückgibst. Und da das temporary weder an eine lokale Variable zugewiesen wird noch deren Lebensdauer durch Bindung an eine const-Referenz verlängert wird erzeugt derctime
Aufruf UB, weil das Temporary da schon wieder zerstört wurde.Kannst du das bitte genauer erklären? Lebt das Temporary nicht auf jeden Fall so lange, bis der äußere Aufruf von ctime abgeschlossen ist?
siehe https://en.cppreference.com/w/cpp/language/lifetime
All temporary objects are destroyed as the last step in evaluating the full-expression that (lexically) contains the point where they were created, and if multiple temporary objects were created, they are destroyed in the order opposite to the order of creation. This is true even if that evaluation ends in throwing an exception.
Huch, hast recht! Ich bin davon ausgegangen, dass das temporäre
MyDate
Objekt direkt nach demGetTimePointer()
Aufruf zerstört wird, weil es nicht mehr benötigt wird und nur der Zeiger weiterverwendet wird.
-
@EinNutzer0 sagte in Datums berechnungen:
@manni66 Nö, es ist ein ganz eindeutiges Beispiel gewählt worden. Ich interpretiere 1.11. als 1.11.2020 und nicht als 1.11.1900.
Dann hättest Du es einfacher machen können, und einfach den 25. Oktober 2020 zurückgeben können ....
-
@Th69 sagte in Datums berechnungen:
Mit "fluent" hat das aber nichts zu tun, da du jedesmal ein neues Objekt erzeugst.
Ja, aber so wie ich es hatte, wäre es fluent UND immutable. Manchmal ist auch immutable gewünscht.
-
@EinNutzer0 sagte in Datums berechnungen:
immutable
Du hast wieder mal keinen Plan mit welchen Wörtern du in der Gegend rumwirfst. Oder du weißt es und bist ein elendiglicher Troll. Derzeit meine favorisierte Theorie zu deiner Person.
-
@Th69 sagte in Datums berechnungen:
Mit "fluent" hat das aber nichts zu tun, da du jedesmal ein neues Objekt erzeugst.
So wäre es richtiger:Da bin ich auch anderer Meinung. Ich hätte das addDays() auch gerne const und sehe kein Problem damit, hier eine Kopie zurückzugeben. Ein Datum ist total billig zu kopieren.
Vielleicht habe ich auch zu viel mit pandas gearbeitet, aber ich vermeide inplace-Operationen sehr gerne. Da addDays vom Namen her misleading sein kann, wäre hier ggf.
operator+
besser. Aber dann braucht man wieder einen ordentlichen Typen für Tage... und so landen wir dann langsam bei einem Nachbau von chrono....
-
@wob sagte in Datums berechnungen:
und so landen wir dann langsam bei einem Nachbau von chrono....
DAS.
-