4

I have a string that contains microseconds since the epoch. How could I convert it to a time structure?

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

int main ()
{
    struct tm tm; 
    char buffer [80];
    char *str ="1435687921000000";
    if(strptime (str, "%s", &tm) == NULL)
        exit(EXIT_FAILURE); 
    if(strftime (buffer,80,"%Y-%m-%d",&tm) == 0)
        exit(EXIT_FAILURE);

    printf("%s\n", buffer);

    return 0;
}
user1024718
  • 573
  • 6
  • 18

4 Answers4

3

Portable solution (assuming 32+ bit int). The following does not assume anything about time_t.

Use mktime() which does not need to have fields limited to their primary range.

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

int main(void) {
  char buffer[80];
  char *str = "1435687921000000";

  // Set the epoch: assume Jan 1, 0:00:00 UTC.
  struct tm tm = { 0 };
  tm.tm_year = 1970 - 1900;
  tm.tm_mday = 1;

  // Adjust the second's field.
  tm.tm_sec = atoll(str) / 1000000;
  tm.tm_isdst = -1;
  if (mktime(&tm) == -1)
    exit(EXIT_FAILURE);
  if (strftime(buffer, 80, "%Y-%m-%d", &tm) == 0)
    exit(EXIT_FAILURE);
  printf("%s\n", buffer);
  return 0;
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

Edit: You could simply truncate the string, since struct tm does not store less than 1 second accuracy.

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

int main ()
{
    struct tm now; 
    time_t secs;
    char buffer [80];
    char str[] ="1435687921000000";
    int len = strlen(str);
    if (len < 7)
        return 1;
    str[len-6] = 0;                     // divide by 1000000
    secs = (time_t)atol(str);
    now = *localtime(&secs);

    strftime(buffer, 80, "%Y-%m-%d", &now);
    printf("%s\n", buffer);

    printf("%s\n", asctime(&now));
    return 0;
}

Program output:

2015-06-30
Tue Jun 30 19:12:01 2015
Weather Vane
  • 33,872
  • 7
  • 36
  • 56
  • "`struct tm` does not store less than 1 second accuracy" is commonly true yet some `struct tm` do support finer fields. – chux - Reinstate Monica Jun 30 '15 at 19:39
  • @chux any examples? OP's question is using only one day's accuracy. – Weather Vane Jun 30 '15 at 19:58
  • 1) The C spec allow it. "The `tm` structure shall contain at _least_ the following (9) members ... `tm_sec`, `tm_min` .. `tm_isdst`" 2) Have not come across one with finer fields in over 10 years. When they do occur, usual it is within another `struct` that encapsulates `struct tm` and the fractional seconds. 3) glibc adds use `long tm_gmtoff` and `const char *tm_zone`. 4) Although OP sample code prints to the day, it is open as to the precision OP truly wants. – chux - Reinstate Monica Jun 30 '15 at 20:18
0

You can convert the microseconds to seconds, and use localtime() like this

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

int main (void)
{
    struct tm *tm; 
    char   buffer[80];
    char  *str = "1435687921000000";
    time_t ms  = strtol(str, NULL, 10);

    /* convert to seconds */
    ms = (time_t) ms / 1E6;
    tm = localtime(&ms);
    if (strftime(buffer, 80, "%Y-%m-%d", tm) == 0)
        return EXIT_FAILURE;

    printf("%s\n", buffer);

    return EXIT_SUCCESS;
}

Note that in the printed date, the microseconds are not present, so you can ignore that part.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
  • 1
    When I compile and run this in MSVC (32 bit compiler) it informs `1970-01-01` (the epoch date). – Weather Vane Jun 30 '15 at 19:10
  • Using `float` as an intermediate type is a bad idea, as it doesn't have adequate precision. Try changing your example to print the time (with seconds) and see if it still matches (for me, it's out by 15 seconds). – Dmitri Jun 30 '15 at 20:39
  • I don't have that compiler and didn't test it there. – Iharob Al Asimi Jun 30 '15 at 21:31
-1

Convert the string to a time_t, then use gmtime(3) or localtime(3).

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

int main () {
        struct tm *tm;
        char buffer [80];
        char *str ="1435687921000000";
        time_t t;

        /* or strtoull */
        t = (time_t)(atoll(str)/1000000);

        tm = gmtime(&t);

        strftime(buffer,80,"%Y-%m-%d",tm);

        printf("%s\n", buffer);

        return 0;
}
user464502
  • 2,203
  • 11
  • 14