从通用时间字符串中获取time_t?

时间:2015-06-18 20:22:02

标签: c++ c

如果我有这个字符串:

2011-10-08T07:07:09Z

是否可以从中获得time_t?如果是这样,怎么办呢?

3 个答案:

答案 0 :(得分:4)

是的,确实如此。首先,使用strptime(3)将其转换为细分时间。这会给你一个struct tm,这是一个分解时间的结构类型。

从那里,您可以使用time_t转换为mktime(3)

以下是一个例子:

#define _XOPEN_SOURCE
#include <time.h>
#include <stdio.h>
#include <string.h>

int main(void) {
        const char *date_example = "2011-10-08T07:07:09Z";
    struct tm broken_down;

    memset(&broken_down, 0, sizeof(broken_down));

    strptime(date_example, "%Y-%m-%dT%H:%M:%SZ", &broken_down);
    broken_down.tm_isdst = 0; // Indicates that DST is not in effect
    time_t epoch_time = mktime(&broken_down);

    // Note: this is platform dependent
    printf("Epoch time: %lld\n", (long long) epoch_time);

    return 0;
}

答案 1 :(得分:1)

使用sscanf()来分解时间。诀窍是以某种方式确定本地和通用时间之间的差异,因此代码可以调用mktime() - 使用假定struct tm是本地时间..

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

int Get_TZ_delta(const struct tm *tmptr) {
  // Make local copy
  struct tm tm = *tmptr;
  time_t t = mktime(&tm);
  struct tm utc_tm = *gmtime(&t);
  time_t t2 = mktime(&utc_tm);
  return (int) difftime(t, t2);
}

time_t UniversalTimeStamp_to_time_t(const char *ts) {
  struct tm tm = { 0 };
  // Use a sentinel to catch extra garbage
  char sentinel;
  if (sscanf(ts, "%d-%2d-%2dT%2d:%2d:%2dZ%c", &tm.tm_year, &tm.tm_mon,
      &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &sentinel) != 6) {
    return -1;
  }
  // struct tm uses offset from 1900 and January is month 0
  tm.tm_year -= 1900;
  tm.tm_mon--;
  // Convert tm from UCT to local standard time
  tm.tm_isdst = 0;
  tm.tm_sec += Get_TZ_delta(&tm);

  time_t t = mktime(&tm); // mktime() assumes tm is local

  // test code
  {
  printf("UTC  `%s`\n", ts);
  char buf[100];
  strftime(buf, sizeof buf, "%Y-%m-%dT%H:%M:%S %Z", &tm);
  printf("Local %s\n", buf);
  printf("Unix  %lld\n\n", (long long) mktime(&tm));
  }

  return t;
}

int main(void) {
  UniversalTimeStamp_to_time_t("2015-06-18T22:07:52Z");
  UniversalTimeStamp_to_time_t("2011-10-08T07:07:09Z");
  UniversalTimeStamp_to_time_t("1970-01-01T00:00:00Z");
  return 0;
}

输出

UTC  `2015-06-18T22:07:52Z`
Local 2015-06-18T17:07:52 CDT
Unix  1434665272

UTC  `2011-10-08T07:07:09Z`
Local 2011-10-08T02:07:09 CDT
Unix  1318057629

UTC  `1970-01-01T00:00:00Z`
Local 1969-12-31T18:00:00 CST
Unix  0

答案 2 :(得分:1)

另一种方法应该是代码知道time_t是自1970年1月1日0:00:00以来的秒数。使用sscanf()来解析字符串,计算天数,然后返回秒数。

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

#define MARCH 3
#define DaysPer400Years   (400*365LL + 97)
#define DaysPer100Years   (100*365LL + 24)
#define DaysPer4Years     (4*365LL + 1)
#define DaysPer1Year      365LL
#define DayNumber1970Jan1 719469LL

long long DayNumber(int year, int Month, int Day, long epoch) {
  long long dn = Day;
  long long y = year;
  y += Month / 12;
  Month %= 12;
  while (Month < MARCH) {
    Month += 12;
    y--;
  }
  // And then a miracle occurs.
  dn += ((Month - MARCH) * (7832 / 4) + (140 / 4)) >> (8 - 2);
  dn += (y / 400) * DaysPer400Years;
  y %= 400;
  dn += (y / 100) * DaysPer100Years;
  y %= 100;
  dn += (y / 4) * DaysPer4Years;
  y %= 4;
  dn += y * DaysPer1Year;
  return dn - epoch;
}

time_t UniversalTimeStamp_to_time_t(const char *ts) {
  int y,m,d,H,M,S;

  // Use a sentinel to catch extra garbage
  char sentinel;
  if (sscanf(ts, "%d-%2d-%2dT%2d:%2d:%2dZ%c", &y, &m,
      &d, &H, &M, &S, &sentinel) != 6) {
    return -1;
  }

  long long t = DayNumber(y, m, d, DayNumber1970Jan1);
  t = t*24L*60*60 + 3600L*H + 60*M + S;

  // test code
  {
  printf("UTC  `%s`\n", ts);
  time_t tt = t;
  struct tm tm = *gmtime(&tt);
  char buf[100];
  strftime(buf, sizeof buf, "%Y-%m-%dT%H:%M:%S %Z", &tm);
  printf("Local %s\n", buf);
  printf("Unix  %lld\n\n", t);
  }

  return t;
}

int main(void) {
  UniversalTimeStamp_to_time_t("2015-06-18T22:07:52Z");
  UniversalTimeStamp_to_time_t("2011-10-08T07:07:09Z");
  UniversalTimeStamp_to_time_t("1970-01-01T00:00:00Z");
  return 0;
}

输出

UTC  `2015-06-18T22:07:52Z`
Local 2015-06-18T22:07:52    
Unix  1434665272

UTC  `2011-10-08T07:07:09Z`
Local 2011-10-08T07:07:09    
Unix  1318057629

UTC  `1970-01-01T00:00:00Z`
Local 1970-01-01T00:00:00    
Unix  0
相关问题