Statt strftime()
der Verwendung der aufgeschlüsselt Zeit struct tm
als ganze Zahl zu formatieren, und es mit atoi()
Parsen, können Sie die einfache, aber nicht dem Standard entsprechende timegm()
-Funktion verwenden.
Auch wenn timegm()
nicht in POSIX ist, wird es von den meisten POSIXy-Systemen bereitgestellt. Wenn Sie Ihren Code wollen über POSIXy Systeme tragbar sein, können Sie eine Abhilfe verwenden (wie in einigen Versionen des timegm
Manpage beschrieben):
#define _POSIX_C_SOURCE 200809L
#define _XOPEN_SOURCE
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
time_t alt_timegm(struct tm *from)
{
char *tz;
time_t result;
int saved_errno;
tz = getenv("TZ");
if (tz)
tz = strdup(tz);
setenv("TZ", "", 1); /* TZ empty refers to UTC */
tzset();
errno = 0;
result = mktime(from);
saved_errno = errno;
setenv("TZ", tz, 1);
free(tz);
errno = saved_errno;
return result;
}
Diese Problemumgehung den Nachteil hat, dass es vorübergehend die aktuelle Zeitzone ändert , die andere Threads betrifft, die zeitzonenbezogene Funktionen ausführen. In einem single-threaded Prozess ist dies kein Problem (da die zeitzonenbezogenen Funktionen nicht async-signal-sicher sind, sollten sie nicht in Signalhandlern verwendet werden).
In multithreaded Programmen sollte man serialisiert werden alle auf die Zeitzone bezogenen Funktionen zugreift - alt_timegm()
oben, mktime()
, localtime()
, und so weiter -, jede Funktion zu gewährleisten, mit dem richtigen Zeitzone Satz laufen.
Die timegm()
Implementierungen in Linux und BSDs sind Thread-sicher; Das heißt, sie ändern die Zeitzone nicht.
die Verwendung der obigen einen String Parsen eines strptime()
Format in ein Unix-Zeitstempel verwendet, ist einfach:
const char *parse_utc(const char *s, const char *format, time_t *to)
{
char *result;
struct tm t_parts;
time_t t;
if (!s || !format) {
errno = EINVAL;
return NULL;
}
result = strptime(s, format, &t_parts);
if (!result) {
errno = EINVAL;
return NULL;
}
errno = 0;
t = alt_timegm(&t_parts);
if (to)
*to = result;
return (const char *)result;
}
Die obige parse_utc()
analysiert eine Zeichenfolge s
mit strptime() Format format
, um to
die UTC-Zeitstempel Speichern, wenn nicht NULL und gibt den Zeiger auf das erste nicht geparste Zeichen in der Zeichenfolge s
zurück.
Einstellung errno = 0
in den oben genannten Funktionen seltsam aussehen, aber es ist, weil die mktime()
(und timegm()
) Funktion kann oder nichterrno
einen Fehler im Fall gesetzt; Es gibt nur (time_t)-1
zurück. Dies bedeutet, dass es unmöglich ist, zuverlässig zu bestimmen, ob eine (time_t)-1
(die der letzten Sekunde des Jahres 1969 in UTC entspricht) ein tatsächlich gültiger Zeitstempel oder eine Fehlerrückkehr ist.
Mit anderen Worten, wenn errno != 0
nach einem Anruf an parse_utc()
, gab es einen Fehler. (Wenn die Zeichenfolge oder das Format ungültig war, gibt parse_utc()
NULL
mit errno == EINVAL
zurück.) Wenn errno == 0
aber *to == (time_t)-1
ist, hängt es von der Architektur ab, ob die Zeitzeichenfolge tatsächlich auf die letzte Sekunde des Jahres 1969 in UTC verweist oder ob es ein Error; wir wissen es einfach nicht.
Da Sie POSIX.1 ['strptime()'] (http://man7.org/linux/man-pages/man3/strptime.3.html) verwenden, sollten Sie das 'posix'-Tag wirklich hinzufügen auf deine Frage! –