web-dev-qa-db-fra.com

comment convertir datetime en timestamp Unix en c?

le scénario est le suivant: je reçois date-heure au format "AAAA-MM-JJ HH: MM: SS" avec libexif. Pour minimiser les coûts d’économie, je souhaite convertir la date/heure en un horodatage Unix ou similaire, qui ne coûte que 64 bits ou 32 bits. Y at-il un moyen explicite avec c?

18
liuliu

Vous pouvez essayer une combinaison de strptime et mktime

struct tm tm;
time_t Epoch;
if ( strptime(timestamp, "%Y-%m-%d %H:%M:%S", &tm) != NULL )
  Epoch = mktime(&tm);
else
  // badness
31
Kjetil Joergensen

Convertissez chaque partie de la date/heure en un entier pour renseigner un struct tm, puis convertissez-la en un time_t à l’aide de mktime .

5
Mark Ransom

Qu'en est-il de sscanf?

struct tm tmVar;
char *strVar = "YYYY-MM-DD HH:MM:SS";
time_t timeVar;
if(sscanf(strVar, "%d-%d-%d %d:%d:%d", &tm.tm_year, /* the other fields */)==6)
    timeVar = mktime(&tmVar);
else
    // bad format

Voici une solution câblée dans c/pseudo-code que je viens de pirater ensemble. Bonne chance!

char * runner = NULL;
char *string_orig = "YYYY-MM-DD HH:MM:SS";
time_t time = 0;
struct tm tmp;

use strstr(string_orig, "-") and atoi foreach

  tmp->tm_year .. 
  tmp->tm_mon  .. 
  tmp->tm_mday ..  
  tmp->tm_hour  .. 
  tmp->tm_min  .. 
  tmp->tm_sec .. 

with *runner as help

time = mktime(&tm)
1
merkuro

Voici un extrait prêt lorsque strptime n'est pas disponible:

#include <stddef.h>
#include <time.h> 
#include <stdio.h> 

time_t string_to_seconds(const char *timestamp_str)
{
    struct tm tm;
    time_t seconds;
    int r;

    if (timestamp_str == NULL) {
        printf("null argument\n");
        return (time_t)-1;
    }
    r = sscanf(timestamp_str, "%d-%d-%d %d:%d:%d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
    if (r != 6) {
        printf("expected %d numbers scanned in %s\n", r, timestamp_str);
        return (time_t)-1;
    }

    tm.tm_year -= 1900;
    tm.tm_mon -= 1;
    tm.tm_isdst = 0;
    seconds = mktime(&tm);
    if (seconds == (time_t)-1) {
        printf("reading time from %s failed\n", timestamp_str);
    }

    return seconds;
}

Ajustez-vous une chaîne dans sscanf à ce dont vous avez besoin. Pour ignorer le fuseau horaire et convertir toujours comme GMT/UTC, soustrayez une timezone (ou _timezone) à seconds (timezone global est défini dans time.h. DST est déjà ignoré par la remise à zéro de tm_isdst champ tm.

0
tutejszy

Linux supporte la fonction getdate(), ce qui me semble plus pratique que d'appeler directement strptime(). En effet, la fonction getdate() vérifie automatiquement les formats many . Cela revient à appeler strptime() avec différents formats jusqu'à ce que la fonction fonctionne ou que tous les formats aient été testés.

// setenv() should be called only once
setenv("DATEMSK", "/usr/share/myprog/datemsk.fmt", 0);

// convert a date
struct tm * t1(getdate("2018-03-31 14:35:46"));
if(t1 == nullptr) ...handle error...
time_t date1(timegm(t1));

// convert another date
struct tm * t2(getdate("03/31/2018 14:35:46"));
if(t2 == nullptr) ...handle error...
time_t date2(timegm(t2));

Remarque: timegm() est similaire à mktime() à la différence près qu’il ignore les paramètres régionaux et utilise le temps universel coordonné. Dans la plupart des cas, c’est le bon moyen de convertir vos dates.

Le fichier datemsk.fmt inclurait au moins ces deux formats pour prendre en charge les dates ci-dessus:

%Y-%b-%d %H:%M:%S
%b/%d/%Y %H:%M:%S

Le nombre de formats pris en charge n'est pas limité, même si vous ne souhaitez pas en avoir trop. Si vous avez trop de formats, ça va être plutôt lent. Vous pouvez également gérer dynamiquement vos formats et appeler strptime() en boucle.

Linux propose également une fonction getdate_r() qui est thread-safe.

Man Page: http://pubs.opengroup.org/onlinepubs/7908799/xsh/getdate.html

0
Alexis Wilke