Datums berechnungen
-
@Swordfish sagte in Datums berechnungen:
Du sagst selbst man soll gefälligst getestete und etablierte Bibliotheken benutzen
Hab ich doch gemacht, oder ist
ctime
etwa keine getestete Bibliothek? Manchmal verstehe ich die Aufregung nicht.
-
Es geht hier um Einiges mehr, der öffentliche Zugriff auf
tp
ist schon Käse. Hast du dir mal überlegt, wo der der Zeiger eigentlich herkommt, auf was er zeigt, und was bei der Verwendung von mehrerenMyDate
Klassen passieren kann?
-
... und bei dem was @DocShoe hier nochmal für Dich verständlich klar ausdrückt liest man halt einfach nicht weiter sondern wirfts weg.
-
Hier bitte, fluent:
#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); } time_t *getTimePointer() { return &my_time; } private: time_t my_time; MyDate(time_t tt) : my_time{tt} {}; }; int main() { std::cout << ctime(MyDate(1, 11).addDays(-7).addDays(14).addDays(-14).getTimePointer()) << "!\n"; std::cout << ctime(MyDate(1, 11).addDays(365).getTimePointer()) << "!\n"; }
Das IST eine funktionierende Lösung ohne zusätzliche Libs. Nur bei
return &my_time;
bin ich mir nicht sicher.Was ist MyDate(28, 2).addDays(1)? Wie soll man das sinnvoll benutzen?
Das würde sich je nach aktuellem Schaljahr richtig verhalten, also im Schaltjahr 29.2. und nicht im Schaltjahr 1.3.
-
@EinNutzer0
Warum gibts du bei getTimePointer() einen Pointer auf Klasseninternas zurück?Damit bindest du die Gültigkeit des Zeigers an die Lebensdauer der Klasse.
-
@EinNutzer0 sagte in Datums berechnungen:
Das IST eine funktionierende Lösung ohne zusätzliche Libs.
Die Lösung steht in Post #3 dieses Threads.
-
@Quiche-Lorraine sagte in Datums berechnungen:
@EinNutzer0
Warum gibts du bei getTimePointer() einen Pointer auf Klasseninternas zurück?Damit bindest du die Gültigkeit des Zeigers an die Lebensdauer der Klasse.
Damit ich die Ausgabe in eine Zeile schreiben könnte.
Wie lange wäre bei
std::cout << ctime(MyDate(1, 11).addDays(365).getTimePointer()) << "!\n";
eigentlich die Lebensdauer der KlasseMyDate
?
-
@Swordfish https://github.com/HowardHinnant/date ist doch eine zusätzliche, externe Lib... KISS-Prinzip.
-
@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.
Also nix " IST eine funktionierende Lösung", da hilft auch Captain Capslock nicht.PS:
Für eine vernünftige Ausgabe überlädt manstd::ostream& operator<<( std::ostream& )
und exponiert keine Klasseninterna.
-
@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.