Arbeiten mit Datum und Uhrzeit in C++: von A bis Z
Das Arbeiten mit Datum und Uhrzeit gehört zu den grundlegenden Aufgaben in der Programmierung. Es wird überall benötigt: von der Ereignisprotokollierung bis zur Berechnung von Fristen und der Erstellung von Diagrammen. Historisch gesehen war dieser Bereich in C++ nicht der benutzerfreundlichste, aber mit der Einführung des Standards C++11 und der folgenden Versionen (C++14, C++17, C++20) hat sich die Situation grundlegend geändert. In diesem Artikel behandeln wir alle wichtigen Aspekte: von den klassischen C-Funktionen bis zur modernen Bibliothek chrono, Timer, Formatierung und Parsing. Das Material ist sowohl für Anfänger als auch für erfahrene Entwickler nützlich, die ihr Wissen systematisieren möchten.
1. Klassischer Ansatz: time_t und die Struktur tm
Vor dem Aufkommen von chrono waren die Funktionen aus <ctime> das wichtigste Werkzeug. Dieser Ansatz bleibt für die Unterstützung von Altcode und einfache Aufgaben relevant.
Wichtige Funktionen:
time()– gibt die aktuelle Zeit alstime_tzurück (Anzahl der Sekunden seit dem 1. Januar 1970).localtime()– wandelttime_tin einetm-Struktur um (lokale Zeit).gmtime()– wandelt in UTC um.strftime()– formatierttmin einen String.mktime()– die umgekehrte Umwandlung:tm→time_t.
#include <iostream>#include <ctime>
int main() { // Aktuelle Zeit abrufen std::time_t now = std::time(nullptr);
// In lokale Zeit umwandeln std::tm* local_tm = std::localtime(&now);
// In einen String formatieren char buffer[80]; std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", local_tm);
std::cout << "Aktuelle Zeit: " << buffer << std::endl; return 0;}Nachteile des Ansatzes:
- Funktioniert nur mit Sekunden (Millisekunden und Mikrosekunden sind nicht verfügbar).
- Nicht threadsicher in Multithread-Umgebungen (verwenden Sie
localtime_runter POSIX). - Die Struktur
tmenthält Felder, die leicht verwechselt werden können (Jahr um 1900 verschoben, Monate ab 0). - Keine Unterstützung für Zeitzonen und Zeitintervalle.
2. Modernes C++: Die chrono-Bibliothek (C++11 und neuer)
Die Bibliothek chrono ist ein leistungsstarkes und typsicheres Werkzeug für die Arbeit mit der Zeit. Sie bildet die Grundlage aller modernen C++-Projekte.
Wichtige Komponenten:
- Uhren (clocks):
system_clock(Systemzeit),steady_clock(monotone Uhr für Messungen),high_resolution_clock(maximale Auflösung). - Zeitpunkte (time_point): an bestimmte Uhren gebunden.
- Dauern (duration): Zeitintervalle (Sekunden, Millisekunden, Nanosekunden).
#include <iostream>#include <chrono>#include <thread>
int main() { using namespace std::chrono;
// Aktueller Zeitpunkt auto now = system_clock::now();
// Zur Anzeige in time_t umwandeln std::time_t now_c = system_clock::to_time_t(now); std::cout << "Aktuelle Zeit: " << std::ctime(&now_c);
// Zeitmessung der Ausführung auto start = steady_clock::now(); std::this_thread::sleep_for(milliseconds(500)); // Arbeit simulieren auto end = steady_clock::now();
auto duration = duration_cast<milliseconds>(end - start); std::cout << "Vergangen: " << duration.count() << " ms" << std::endl;
return 0;}Vorteile von chrono:
- Hohe Genauigkeit (Nanosekunden).
- Typsicherheit (Sekunden und Millisekunden können nicht versehentlich addiert werden).
- Unterstützung für Arithmetik (Addition/Subtraktion von Dauern und Zeitpunkten).
- Unterstützung für verschiedene Uhren und Zeitzonen (C++20).
- Threadsicherheit.
3. Formatierung und Parsing von Datum und Uhrzeit
In C++20 wurde die Unterstützung für die Formatierung und das Parsing von Datum und Uhrzeit mithilfe der Bibliothek <chrono> und der Bibliothek <format> erheblich erweitert.
Formatierung mit std::format (C++20):
#include <iostream>#include <chrono>#include <format>
int main() { using namespace std::chrono;
auto now = system_clock::now(); std::string formatted = std::format("{:%Y-%m-%d %H:%M:%S}", now); std::cout << "Formatiertes Datum: " << formatted << std::endl;
return 0;}Parsing mit std::chrono::parse (C++20):
#include <iostream>#include <chrono>#include <sstream>
int main() { using namespace std::chrono;
std::string date_str = "2024-03-15 14:30:00"; std::istringstream iss(date_str); sys_seconds tp; iss >> parse("%Y-%m-%d %H:%M:%S", tp);
if (iss.fail()) { std::cerr << "Parsing-Fehler" << std::endl; return 1; }
std::cout << "Geparste Zeit: " << tp << std::endl; return 0;}Wichtige Formatierungsspezifikatoren:
%Y– Jahr (4 Ziffern)%m– Monat (01-12)%d– Tag (01-31)%H– Stunde (00-23)%M– Minute (00-59)%S– Sekunde (00-60)%z– Zeitzonenversatz (z. B. +0200)%Z– Zeitzonenabkürzung (z. B. CET)
4. Timer und Verzögerungen
Timer werden verwendet, um Code nach einer bestimmten Zeitspanne oder in regelmäßigen Abständen auszuführen.
Einfache Verzögerung mit std::this_thread::sleep_for:
#include <iostream>#include <chrono>#include <thread>
int main() { std::cout << "Start" << std::endl; std::this_thread::sleep_for(std::chrono::seconds(2)); std::cout << "Nach 2 Sekunden" << std::endl; return 0;}Timer mit std::chrono::steady_clock für Messungen:
#include <iostream>#include <chrono>
int main() { using namespace std::chrono;
auto start = steady_clock::now();
// Einige Operationen volatile int sum = 0; for (int i = 0; i < 1000000; ++i) { sum += i; }
auto end = steady_clock::now(); auto elapsed = duration_cast<microseconds>(end - start); std::cout << "Ausführungszeit: " << elapsed.count() << " Mikrosekunden" << std::endl;
return 0;}5. Arbeiten mit Zeitzonen (C++20)
In C++20 wurde die Unterstützung für Zeitzonen mithilfe der IANA-Zeitzonendatenbank hinzugefügt.
#include <iostream>#include <chrono>
int main() { using namespace std::chrono;
auto now = system_clock::now();
// Zeit in der Zeitzone "Europe/Berlin" anzeigen auto berlin_tz = locate_zone("Europe/Berlin"); zoned_time berlin_time{berlin_tz, now}; std::cout << "Zeit in Berlin: " << berlin_time << std::endl;
// Zeit in der Zeitzone "America/New_York" anzeigen auto ny_tz = locate_zone("America/New_York"); zoned_time ny_time{ny_tz, now}; std::cout << "Zeit in New York: " << ny_time << std::endl;
return 0;}6. Praktische Beispiele und bewährte Verfahren
Beispiel 1: Berechnung der Differenz zwischen zwei Daten
#include <iostream>#include <chrono>
int main() { using namespace std::chrono;
// Daten festlegen sys_days start = 2024y / January / 1; sys_days end = 2024y / December / 31;
// Differenz berechnen auto diff = end - start; std::cout << "Tage zwischen den Daten: " << diff.count() << std::endl;
return 0;}Beispiel 2: Überprüfung, ob ein Datum ein Wochenende ist
#include <iostream>#include <chrono>
int main() { using namespace std::chrono;
auto today = floor<days>(system_clock::now()); weekday wd{today};
if (wd == Saturday || wd == Sunday) { std::cout << "Heute ist ein Wochenende!" << std::endl; } else { std::cout << "Heute ist ein Werktag." << std::endl; }
return 0;}Empfehlungen:
- Verwenden Sie für neue Projekte
chronoanstelle vonctime. - Verwenden Sie für Messungen
steady_clock(nichtsystem_clock, das angepasst werden kann). - Verwenden Sie für die Formatierung und das Parsing
std::formatundstd::chrono::parse(C++20). - Berücksichtigen Sie Zeitzonen, wenn Ihre Anwendung mit Benutzern aus verschiedenen Regionen arbeitet.
- Vermeiden Sie die direkte Verwendung von
time_tin neuem Code.
Fazit
Die Arbeit mit Datum und Uhrzeit in C++ hat einen langen Weg von den einfachen C-Funktionen bis zur leistungsstarken und typsicheren chrono-Bibliothek zurückgelegt. Moderne C++-Standards bieten alle notwendigen Werkzeuge für die bequeme und korrekte Arbeit mit der Zeit: hohe Genauigkeit, Unterstützung für Zeitzonen, bequeme Formatierung und Parsing. Die Verwendung von chrono macht den Code zuverlässiger, lesbarer und portabler. Wir hoffen, dass dieser Leitfaden Ihnen hilft, die Arbeit mit Datum und Uhrzeit in Ihren C++-Projekten zu meistern!