11

Does anyone know how to go from an ISO-8601-formatted date/time string to a time_t? I am using C++ and it needs to work on Windows and Mac.

I have written the code but I am sure there is a version that is more "standard."

I will get a date like 2011-03-21 20:25 and I have to tell if the time is in the past or the future.

Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
reza
  • 5,972
  • 15
  • 84
  • 126
  • 2
    There's a similar discussion about a cross-platform `strptime` [here](http://stackoverflow.com/questions/321849/strptime-equivalent-on-windows). You may want ravenspoint's answer, and use boost: `#include "boost/date_time/posix_time/posix_time.hpp"` – Tim Mar 21 '11 at 21:23

4 Answers4

8

One ugly hack I thought would be fun: since you only want to determine which date/time is bigger, you can convert the date to string and compare strings. ;-) (The upside is you do not need strptime which is not available everywhere.)

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

int main(int argc, char *argv[])
{
    const char *str = "2011-03-21 20:25";
    char nowbuf[100];
    time_t now = time(0);
    struct tm *nowtm;
    nowtm = localtime(&now);
    strftime(nowbuf, sizeof(nowbuf), "%Y-%m-%d %H:%M", nowtm);
    if (strncmp(str, nowbuf, strlen(str)) >= 0) puts("future"); else puts("past");
    return 0;
}
Mormegil
  • 7,955
  • 4
  • 42
  • 77
  • 3
    While I instinctively cringe at such an idea... that is the point of the "YYYYMMDD HHMMSS" format - ascii comparisons actually work. The risk, of course is if he starts getting dates in a different format in the future. – Tim Mar 21 '11 at 21:19
7

You can use strptime to convert from a string to a struct tm, and then you can use mktime to convert from a struct tm to a time_t. For example:

// Error checking omitted for expository purposes
const char *timestr = "2011-03-21 20:25";
struct tm t;
strptime(timestr, "%Y-%m-%d %H:%M", &t);
time_t t2 = mktime(&t);
// Now compare t2 with time(NULL) etc.
Mark Lakata
  • 19,989
  • 5
  • 106
  • 123
Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
  • 2
    strptime isn't standard c. Will it be available on Windows? – Null Set Mar 21 '11 at 21:12
  • 1
    @Null Set: Oops you're right, forgot about that. `strptime` is only defined by POSIX. See http://stackoverflow.com/questions/321849/strptime-equivalent-on-windows and http://stackoverflow.com/questions/667250/strptime-in-windows . – Adam Rosenfield Mar 22 '11 at 18:32
1

If the timestamp is in the local timezone the following method converts from ISO8601 to UTC. Also it is not ignoring potential daylight saving. It is standard C99.

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

time_t from_iso8601_utc(const char* dateStr)
{
    struct tm t;
    int success = sscanf(dateStr, "%d-%d-%dT%d:%dZ", /* */
                         &t.tm_year, &t.tm_mon, &t.tm_mday, &t.tm_hour, &t.tm_min);
    if (success != 5) {
        return 0;
    }

    /* compensate expected ranges */
    t.tm_year = t.tm_year - 1900;
    t.tm_mon = t.tm_mon - 1;
    t.tm_sec = 0;
    t.tm_wday = 0;
    t.tm_yday = 0;
    t.tm_isdst = 0;

    time_t localTime = mktime(&t);
    time_t utcTime = localTime - timezone;
    return utcTime;
}
Peter Kofler
  • 9,252
  • 8
  • 51
  • 79
0

Inspired from @Peter Kofler answer for 2022-12-13T17:15:53.499Z kind of dates:

int64_t dateTime_parse(char *dateString)
{
  char *format = "%d-%d-%dT%d:%d:%d.%dZ";
  
  struct tm t{};
  int msec;
  int parseCount = sscanf(dateString, format, &t.tm_year, &t.tm_mon, 
                          &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec, &msec);
  if (parseCount < 7)
  {
    return - 1;
  }
  t.tm_year -= 1900;
  t.tm_mon -= 1;
  t.tm_isdst = -1;               //let mktime figure out DST

  int64_t result = mktime(&t);   //this is time_t type
  result *= 1000;
  result += msec;

  return result;
}

Note that mktime assumes first parameter to be a pointer to local time. If you want the date string to be parsed as UTC, use _mkgmtime instead (in windows).

zzxoto
  • 62
  • 6