====== Zeit-Funktionen ====== __Überblick:__ * **[[zeit-funktionen#time()]]** - Anzahl der Sekunden, die seit dem 01.01.1970, 00:00:00 Uhr, vergangen sind. (Evtl. das "Jahr 2038"-Problem, wenn "time_t" als "long" implementiert ist.) * **[[zeit-funktionen#localtime_und_gmtime|localtime()]]** - Umwandeln von "time_t" (das Ergebnis von "time()") in "struct tm" (als lokale Ortszeit) unter der Berücksichtigung von Sommer- und Winterzeit. * localtime_s() * localtime_r() * **[[zeit-funktionen#localtime_und_gmtime|gmtime()]]** - Wie localtime(), nur das Ergebnis ist nicht die lokale Ortszeit, sondern die UTC-Zeit. * **[[zeit-funktionen#mktime()]]** - Umwandeln von "struct tm" in "time_t" (Gegenstück der Funktionen localtime() und gmtime()). * **[[zeit-funktionen#difftime()]]** – Differenz zwischen zwei Zeitangaben. * asctime() und ctime() – Umwandeln von Zeitformaten ("struct tm" und "time_t") in einen String. * **strftime()** – Umwandeln vom Zeitformat "struct tm" in einen benutzerdefinierten String. * **[[zeit-funktionen#clock()]]** - Verbrauchte CPU-Zeit für ein Programm (seit dem Programmstart).\\ [[http://man7.org/linux/man-pages/man3/clock.3.html]] * **clock_gettime()** (CLOCK_MONOTONIC, CLOCK_MONOTONIC_PRECISE, CLOCK_REALTIME, CLOCK_PROCESS_CPUTIME_ID)\\ [[http://man7.org/linux/man-pages/man2/clock_gettime.2.html]] * **TZ** (Environment Variable) - Zeitzone (Beispiele: "localtime", "MESZ", "UTC", etc.) * FIXME :!: UTC (Universal Time Coordinated) ist identisch mit GMT (Greenwich Mean Time). __Datentypen:__ * **clock_t** - Die CPU-Zeit (Ganzzahl) * **time_t** - Datums- und Zeitangaben (Ganzzahl) * **struct tm** - Enthält alle zu einer (gregorianischen) Kalenderzeit relevanten Komponenten: struct tm { int tm_sec; // Sekunden (0–59) int tm_min; // Minuten (0–59) int tm_hour; // Stunden (0–23) int tm_mday; // Monatstag (1–31) int tm_mon; // Monate (0–11; Januar = 0) int tm_year; // Jahre ab 1900 int tm_wday; // Tag seit Sonntag (0–6; Sonntag = 0) int tm_yday; // Tag seit 1. Januar (0–365; 1.Januar = 0) int tm_isdst; // Winter-/Sommerzeit (Winterzeit: tm_istdst == 0; Sommerzeit: tm_isdst > 0; wenn Info nicht verfügbar: tm_isdst < 0) long int tm_gmtoff; // (nur auf Linux) Gibt die Sekunden östlich von UTC bzw. den negativen Wert westlich von UTC für die Zeitzonen an. const char *tm_zone; // (nur auf Linux) Enthält den Namen der aktuellen Zeitzone. }; * **struct timespec** - Enthält (hoch aufgelöste) Zeit: struct timespec { time_t tv_sec; // Sekunden long tv_nsec; // Nanosekunden }; Je nach OS verfügbare Funktionen (Quelle: [[http://nadeausoftware.com/articles/2012/04/c_c_tip_how_measure_elapsed_real_time_benchmarking]]): ^ ^AIX ^BSD ^HP-UX ^Linux ^OSX ^Solaris^Windows^ |time() | X | X | X | X | X | X | | |clock_gettime()| X | X | X | X | | X | | |gethrtime() | | | X | | | X | | |gettimeofday() | X | X | X | X | X | X | | |mach_absolute_time()| | | | | X | | | |GetSystemTimeAsFileTime()\\ GetSystemTimePreciseAsFileTime() | | | | | | | X | Je nach OS verfügbare Clock-IDs: ^Clock-ID ^AIX ^BSD ^HP-UX ^Linux ^Solaris^Hinweis ^ |CLOCK_REALTIME | X | X | X | X | X |Reports a settable (by root) time that can be mapped to the **current real-world date and time**. The value is the elapsed time since "the Epoch", which is usually **Jan 1st, 1970** at midnight GMT (this may vary among OSes and should not be counted on). %%CLOCK_REALTIME%% is the system time used for human time display, so it's subject to corrections whenever the system checks a time server or the system administrator updates the clock. If such adjustments are made during benchmarking, then the elapsed time between two queries of %%CLOCK_REALTIME%% will be wrong. One of the other clocks should be used instead, if available. | |CLOCK_MONOTONIC | X | X | | X | X |Reports an **//unsettable//** time that counts upwards starting at an unspecified **time zero in the past** that's typically the system's boot time. The time from %%CLOCK_MONOTONIC%% cannot be mapped to the current real-world date and time, but it's the **right tool for benchmarking** where we only need to find the elapsed time of an algorithm. | |CLOCK_MONOTONIC_PRECISE| | X | | | |Is a variant of %%CLOCK_MONOTONIC%% that aims at providing a more precise time. | |CLOCK_MONOTONIC_RAW | | | | X | |(Linux 2.6.28 or later) Is a variant of %%CLOCK_MONOTONIC%% that aims for sa more precise time by accessing the underlying "raw" hardware-based time. | |CLOCK_HIGHRES | | | | | X |Is equivalent to %%CLOCK_MONOTONIC%% and aims at returning a high-resolution time. The returned value is also available from gethrtime(). | __Deklarationen, Beschreibungen und Beispiele:__ ===== time() ===== Deklaration in time_t time(time_t *ptr_TimeVar); FIXME ===== localtime() und gmtime() ===== struct tm *localtime(const time_t *ptr_TimeVar); struct tm *gmtime(const time_t *ptr_TimeVar); Beide Funktionen liefern als Rückgabewert einen Pointer auf "ptr_TimeVar" vom Typ "struct tm". Die Funktion localtime() wandelt die Kalenderzeit in die lokale Ortszeit um (unter der Berücksichtigung von Sommer- und Winterzeit), gmtime() dagegen - in die UTC-Zeit. ===== mktime() ===== time_t mktime(struct tm *ptr_TimeVar); Auf diese Weise wird eine Zeit im "struct tm"-Format wieder in eine Zeit im "time_t"-Format umgewandelt ("tm_yday" und "tm_wday" in "ptr_TimeVar" werden ignoriert). Der zulässige Bereich für die Kalenderzeit liegt zwischen dem 01.01.1970, 00:00:00 Uhr, und dem 19.01.2038, 03:14:07 Uhr. Ist die Kalenderzeit nicht darstellbar, gibt diese Funktion –1 zurück. Befinden sich die Felder "tm_sec", "tm_min", "tm_hour", "tm_mday" und "tm_mon" nicht im korrekten Bereich, werden diese angepasst. ===== difftime() ===== double difftime(time_t zeit_nachher, time_t zeit_vorher); Die difftime() liefert die Differenz von "zeit_nachher" minus "zeit_vorher" (in Sekunden) zurück (als **double**-Wert!). ===== clock() ===== clock_t clock(void); Die clock() liefert die verbrauchte CPU-Zeit (:!: nicht in Sekunden!) seit dem Programmstart zurück (-1 im Fehlerfall). Um die CPU-Zeit in Sekunden zu berechnen, muss man der Rückgabewert durch **CLOCKS_PER_SEC** teilen. ===== Beispiel: "class timeutils" ===== Klasse, um die (aktuelle) Zeit in verschiedenen Formaten auszugeben: **timeutils.h** namespace utils { struct timeformats { static const char* FMT_ISO_DATE; // Equivalent to "%Y-%m-%d" (the ISO 8601 date format). static const char* FMT_ISO_TIME; // Equivalent to "%H:%M". static const char* FMT_ISO_TIME_SEC; // Equivalent to "%H:%M:%S" (the ISO 8601 time format). static const char* FMT_ISO_DATE_TIME_SEC; // FMT_ISO_DATE + FMT_ISO_TIME_SEC. static const char* FMT_FILENAME_DATE; // Equivalent to "%Y%m%d". static const char* FMT_FILENAME_TIME; // Equivalent to "%H%M%S". static const char* FMT_TIME_SEC_MS; // Equivalent to "%H:%M:%S.%ffff" (the ISO 8601 time format) + milliseconds. static const char* FMT_STOPWATCH_TIME; // Custom format "%k". static const char* FMT_DATE_TIME_SEC_MS; // FMT_ISO_DATE + FMT_ISO_TIME_SEC + ".%ffff". }; // struct timeformats class timeutils // Helper rund um Zeitangaben. { public: timeutils() = delete; ~timeutils() = delete; public: static std::time_t now(); // now() liefert die Zeit sekundengenau (alterantiv hires_time() verwenden. static string to_string(const std::time_t& time, const string& format); // Formatiert nach http://en.cppreference.com/w/cpp/chrono/c/strftime". }; // class timeutils // --- Inlines: --- inline std::time_t timeutils::now() { return std::time(nullptr); } } // namespace utils **timeutils.cpp** namespace utils { // Hinweis: %F, %R, %T werden von VS2012 nicht unterstützt. const char* timeformats::FMT_ISO_DATE = "%Y-%m-%d"; // Equivalent to "%Y-%m-%d" (the ISO 8601 date format). const char* timeformats::FMT_ISO_TIME = "%H:%M"; // Equivalent to "%H:%M". const char* timeformats::FMT_ISO_TIME_SEC = "%H:%M:%S"; // Equivalent to "%H:%M:%S" (the ISO 8601 time format). const char* timeformats::FMT_ISO_DATE_TIME_SEC = "%Y-%m-%d %H:%M:%S"; // FMT_ISO_DATE + FMT_ISO_TIME_SEC. const char* timeformats::FMT_FILENAME_DATE = "%Y%m%d"; // Equivalent to "%Y%m%d". const char* timeformats::FMT_FILENAME_TIME = "%H%M%S"; // Equivalent to "%H%M%S". const char* timeformats::FMT_TIME_SEC_MS = "%H:%M:%S.%ffff"; // Equivalent to "%H:%M:%S.%ffff" (the ISO 8601 time format) + milliseconds. const char* timeformats::FMT_STOPWATCH_TIME = "%k"; // Custom format "%k". const char* timeformats::FMT_DATE_TIME_SEC_MS = "%Y-%m-%d %H:%M:%S.%ffff"; // FMT_ISO_DATE + FMT_ISO_TIME_SEC + ".%ffff". string timeutils::to_string(std::time_t const& time, string const& format) // Formatiert nach "http://en.cppreference.com/w/cpp/chrono/c/strftime". { char buffer[256]; struct tm tm_struct; #ifdef OS_WINDOWS localtime_s(&tm_struct, &time); #else localtime_r(&time, &tm_struct); #endif if (std::strftime(buffer, sizeof(buffer), format.c_str(), &tm_struct)) return buffer; return string(); } // timeutils::to_string() } // namespace utils ===== Weitere Beispiele ===== // IN ARBEIT void testFunktion() { time_t t = time(NULL); struct tm tm; #ifdef OS_WINDOWS localtime_s(&tm, &t); #else // Unix, Linux localtime_r(&t, &tm); #endif printf("Jahr = %d\n", tm.tm_year + 1900); printf("Monat = %d\n", tm.tm_mon + 1); printf("Tag = %d\n", tm.tm_mday); } // NICHT FERTIG :!: Zu beachten, daß Ergebniss, das die Funktionen localtime(), localtime_s(), localtime_r() liefern, von dem Wert der **Environment Variable "%%TZ%%"** abhängt. Hier beispielsweise die Einstellung für die mitteleuropäische Sommerzeit: export TZ=MESZ Ein Blogpost erklärt, warum das Setzen der Timezone-Variable TZ tausende von Syscalls erspart: [[https://blog.packagecloud.io/eng/2017/02/21/set-environment-variable-save-thousands-of-system-calls/]] Weitere Infos hier: [[http://blog.quasardb.net/a-portable-high-resolution-timestamp-in-c/]]\\ ...oder hier: **[[http://nadeausoftware.com/articles/2012/04/c_c_tip_how_measure_elapsed_real_time_benchmarking]]** - :!: Sehr ausführliche Analyse! Fortgeschrittene Funktionen in der Zeitbibliothek von C++11: [[http://www.linux-magazin.de/Ausgaben/2016/06/C-11]] ---- Stand: 23.01.2020\\ --- //[[feedback.jk-wiki@kreick.de|: Jürgen Kreick]]// EOF