2017-03-02 2 views
0

Ich habe den folgenden Code geschrieben, um Datum in Zeitstempel zu konvertieren.Datum in Epoche umrechnen Systemzeitzone ignorieren

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <time.h> 

int main() 
{ 
    struct tm date_time; 
    char date_time_buf[255]; 
    char date_time_hdr[255]={0}; 
    strncpy(date_time_hdr,"Thu, 02 Mar 2017 05:54:28 GMT",255); 
    memset(&date_time, 0, sizeof(struct tm)); 
    strptime(date_time_hdr, "%a, %d %b %Y %H:%M:%S %Z", &date_time); 
    memset(date_time_buf, 0, 255); 
    strftime(date_time_buf, 255, "%s", &date_time); 
    int p=atoi(date_time_buf); 
    printf("time is %d \r\n", p); 
    return 0; 
} 

Ich bin in der Lage, Datum zu Timestamp zu konvertieren. Aber mit einem Problem konfrontiert. Der Zeitstempel ist um 5 Stunden 30 Minuten versetzt, was die Zeitzone meiner Linuxmaschine ist. Aber das will ich nicht. Gibt es eine Möglichkeit, die Systemzeitzone zu ignorieren?

+0

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! –

Antwort

0

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.

Verwandte Themen