Как конвертировать дату и время в Unix в c? - PullRequest
18 голосов
/ 16 июня 2009

сценарий: я получаю дату и время в формате "ГГГГ-ММ-ДД ЧЧ: ММ: СС" с libexif Чтобы свести к минимуму экономию средств, я хочу преобразовать дату и время в метку времени Unix или аналогичную, которая стоит всего 64 или 32 бита. Есть ли явный способ с c?

Ответы [ 6 ]

31 голосов
/ 16 июня 2009

Вы можете попробовать комбинацию strptime и mktime

struct tm tm;
time_t epoch;
if ( strptime(timestamp, "%Y-%m-%d %H:%M:%S", &tm) != NULL )
  epoch = mktime(&tm);
else
  // badness
5 голосов
/ 16 июня 2009

Конвертируйте каждую часть даты / времени в целое число, чтобы заполнить struct tm, затем преобразуйте его в time_t, используя mktime .

1 голос
/ 11 июля 2014

А как насчет 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
1 голос
/ 16 июня 2009

Вот проводное решение в c / псевдокоде, которое я только что взломал. Удачи!

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)
0 голосов
/ 01 апреля 2018

Linux поддерживает функцию getdate(), которая, на мой взгляд, более практична, чем прямой вызов strptime(). Это связано с тем, что функция getdate() автоматически проверяет многие форматы. Это эквивалентно вызову strptime() с различными форматами, пока функция не сработает или все форматы не будут протестированы.

// 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));

Примечание: timegm() похоже на mktime() за исключением того, что оно игнорирует локаль и использует UTC. В большинстве случаев это правильный способ конвертировать ваши даты.

Файл datemsk.fmt будет содержать как минимум следующие два формата для поддержки вышеуказанных дат:

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

Количество поддерживаемых форматов не ограничено, хотя, возможно, вы не захотите иметь их слишком много. Это будет довольно медленно, если у вас слишком много форматов. Вы также можете динамически управлять форматами и вызывать strptime() в цикле.

Linux также предлагает функцию getdate_r(), которая является поточно-ориентированной.

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

0 голосов
/ 04 июля 2017

Вот готовый фрагмент, когда strptime недоступен:

#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;
}

Настройте в sscanf строку на то, что вам нужно. Чтобы игнорировать часовой пояс и всегда преобразовывать как GMT / UTC, вычтите a timezone (или _timezone) из seconds (timezone global определяется во времени. Ч. DST уже игнорируется путем обнуления поля tm_isdst поля tm.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...