ctimetime-t

Converting seconds since epoch to time_t


I have a string representing seconds since epoch, and I need to convert it to a human readable string. I've seen a few posts online that suggest simply casting an integer to time_t as so:

time_t time = (time_t)(atoi(secs_since_epoch_str));

But, if I look up the definition of time_t:

typedef /* unspecified */ time_t;

Although not defined by the C standard, this is almost always an integral 
value holding the number of seconds (not counting leap seconds) since 00:00,
Jan 1 1970 UTC, corresponding to POSIX time.

So, this is not guaranteed to work. I'm wondering if there's a proper way of doing this?


Solution

  • Converting seconds since epoch to time_t
    I have a string representing seconds since epoch, and I need to convert it to a human readable string.

    Add the seconds offset to a .tm_sec member of an epoch struct tm and form the time_t.


    1. Convert the string to an wide integer. (Here I assume the string represents a whole number of seconds.) It may be wider than long. Error handling omitted for brevity.
        long long offset = strtoll(string, NULL, 10);
        // or pedantically
        intmax_t offset = strtoimax(string, NULL, 10);
    
    1. Consider cases where time_t is not certainly a count of seconds (e.g. maybe nanoseconds) and maybe the epoch is not Jan 1, 1970 - it is more interesting. Form a timestamp for the epoch.
        time_t epoch = 0;
        struct tm *tm_ptr = localtime(&epoch);
        if (tm_ptr == NULL) Handle_Error();
        struct tm tm = *tm_ptr;
    
    1. Add to the struct tm members. Perhaps segmented the offset addition into parts to avoid int overflow. More code needed when int is 16-bit and offset is large (e. g. 88+ years).
        tm.tm_sec += offset%60;
        offset /= 60;
        tm.tm_min += offset%60;
        offset /= 60;
        tm.tm_hour += offset%24;
        offset /= 24;
        tm.tm_mday += offset;
    
    1. Call mktime() to bring the timestamp into the primary range and print. Note than since time_t might be some integer type or some floating point type, covert to a FP type to print.
        time_t target = mktime(&tm);
        printf("%Lg\n", (long double) target);
        if (target == -1) Handle_Error();
        printf("%s", asctime(&tm));