====== 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