Kacper
Kacper

Reputation: 268

C time difference

I am trying to diff two dates in C, but I receive such output:

future date: 18-11-2013 22:8

current date: 18-11-2013 22:8

Here comes my code:

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

int main(int argc, char *argv[])
{   
    // 2 years ahead
    time_t unixtime = time(NULL);
    struct tm *future = localtime(&unixtime);
    future->tm_year += 2;

    // current time
    time_t unixtime_now = time(NULL);
    struct tm *current = localtime(&unixtime_now);

    printf("future date: %d-%d-%d %d:%d\n", future->tm_mday, 1 + future->tm_mon, 1900 + future->tm_year, future->tm_hour, future->tm_min);
    printf("current date: %d-%d-%d %d:%d\n", current->tm_mday, 1 + current->tm_mon, 1900 + current->tm_year, current->tm_hour, current->tm_min);

    return 0;
}

Upvotes: 0

Views: 814

Answers (2)

nos
nos

Reputation: 229342

That's because localtime() is not reentrant.

When you do

struct tm *future = localtime(&unixtime);
 ... 
struct tm *current = localtime(&unixtime_now);

the first call returns a pointer to some static location managed by the runtime. The second call uses that same location to store the data. So now both future and current point to the exact same thing.

You need to copy out the struct tm into storage that you manage yourself: e.g.

struct tm future = *localtime(&unixtime);
 ... 
struct tm current = *localtime(&unixtime_now);

Or use the more appropriate localtime_r function if it's available on your platform.

struct tm future;
localtime_r(&unixtime, &future);
 ... 
struct tm current;
localtime_r(&unixtime, &current);

Upvotes: 2

svk
svk

Reputation: 5919

The return value of localtime is a pointer to a statically allocated struct which may be overwritten by further calls to date/time functions. If you want to keep the pointed-to data around for longer, you need to make a copy of it, or use another function such as localtime_r.

See the localtime(3) man page:

The localtime() function converts the calendar time timep to broken-down time representation, expressed relative to the user's specified timezone. The function acts as if it called tzset(3) and sets the external variables tzname with information about the current timezone, timezone with the difference between Coordinated Universal Time (UTC) and local standard time in seconds, and daylight to a nonzero value if daylight savings time rules apply during some part of the year. The return value points to a statically allocated struct which might be overwritten by subsequent calls to any of the date and time functions. The localtime_r() function does the same, but stores the data in a user-supplied struct. It need not set tzname, timezone, and daylight.

Upvotes: 2

Related Questions