dtrunk
dtrunk

Reputation: 4805

Wrong time with localtime()

Running dateon my server results in the correct time. But using localtime() in C(++) I'm getting the wrong time.

Running date: Fr 30. Nov 12:15:36 CET 2012

Using localtime(): Fr 30 Nov 2012 11:15:36 CET

What's wrong here?

OS: Debian 5.0.10

Some code:

struct tm* today;
today = localtime(...);
strftime(timeBuffer,50,myConnection.getMetaData().getDateFormat().c_str(),today);

Upvotes: 2

Views: 9579

Answers (4)

Joze
Joze

Reputation: 1305

Did you try this ? :

 time_t rawtime;
 struct tm * today;

 time ( &rawtime );
 today= localtime ( &rawtime );
 puts(asctime (today));

Upvotes: 0

Sander De Dycker
Sander De Dycker

Reputation: 16243

disclaimer : This answer was written before any mention of strftime was added, and was a gut reaction to the 1 hour difference in the timestamps. Looking back at it now, that 1 hour difference couldn't have been due to DST (because the dates are not in summer), but is likely showing a UTC timestamp (1 hour difference between UTC and CET).

Unfortunately, the answer was accepted, and so I can't delete it. Even more unfortunate, is that the question as it stands is not answerable without additional information.

Leaving the original answer here for full transparency, but know that it does not address the question as asked :

The struct tm returned by localtime has a tm_isdst field that indicates whether daylight saving time (DST) is in effect. You need to take that field into account when formatting the time.

Try using asctime to format the time eg. :

puts(asctime(today));

Upvotes: 2

Michael Paxton
Michael Paxton

Reputation: 21

I have experienced the same problem while writing a date adjustment routine. Adding 86400 seconds (= 1 day) to any given datetime value should result in incrementing the datetime value by one day. However in testing, the output value invariably added exactly one hour to the expected output. For instance, '2019-03-20 00:00:00' incremented by 86400 seconds resulted in '2019-03-21 01:00:00'. The reverse also occurred: '2019-03-21 00:00:00' decremented by -86400 resulted in '2019-03-20 01:00:00'.

The solution (inexplicably) was to subtract 3600 seconds (one hour) from the final interval before applying it to the input datetime.

The solution (thanks to helpful comments from @Lightness-Races-in-Orbit) was to set tm_isdst to -1 before calling mktime(). This tells mktime() that the DST status for the input datetime value is unknown, and that mktime() should use the system timezone databases to determine the correct timezone for the input datetime value.

The function (as corrected below) allows for any integer adjustment of days and now produces consistently correct results:

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

/*******************************************************************************
 *  \fn             adjust_date()
 *******************************************************************************/

int adjust_date(
                        char    *original_date,
                        char    *adjusted_date,
                        char    *pattern_in,
                        char    *pattern_out,
                        int      adjustment,
                        size_t   out_size)
{
/*
struct tm {
    int tm_sec;         // seconds          0-59
    int tm_min;         // minutes          0-59
    int tm_hour;        // hours            0-23
    int tm_mday;        // day of the month 1-31
    int tm_mon;         // month            0-11
    int tm_year;        // year       minus 1900
    int tm_wday;        // day of the week  0-6
    int tm_yday;        // day in the year  0-365
    int tm_isdst;       // daylight saving time 
};
*/
    struct tm day;

    time_t one_day = 86400;
//  time_t interval = (one_day * adjustment) - 3600;
    time_t interval = (one_day * adjustment);

    strptime(original_date, pattern_in, &day);

    day.tm_isdst = -1;
    time_t t1 = mktime(&day);

    if (t1 == -1) {
        printf("The mktime() function failed");
        return -1;
    }

    time_t t2 = t1 + interval;

    struct tm *ptm = localtime(&t2);

    if (ptm == NULL) {
        printf("The localtime() function failed");
        return -1;
    }

    strftime(adjusted_date, out_size, pattern_out, ptm);

    return 0;
}

/*******************************************************************************
 *  \fn             main()
 *******************************************************************************/
int main()
{
    char    in_date[64]     = "20190321000000" ,
            out_date[64],
            pattern_in[64]  = "%Y%m%d%H%M%S",
            pattern_out[64] = "%Y-%m-%d %H:%M:%S";

    int     day_diff = -1,
            ret = 0;

    size_t  out_size = 64;

    memset(out_date, 0, sizeof(out_date));

    ret = adjust_date(in_date, out_date, pattern_in, pattern_out, day_diff, out_size); 

    if (ret == 0)
    {
        printf("Adjusted date: '%s'\n", out_date);
    }

    return ret;
}

Hopefully, this will be of some help to somebody. Your constructive comments are greatly appreciated.

Upvotes: 1

stefan
stefan

Reputation: 3749

handling date time is very error prone and usually badly tested. i always recommend using boost::date_time http://www.boost.org/doc/libs/1_52_0/doc/html/date_time.html

here are nice examples http://en.highscore.de/cpp/boost/datetime.html

Upvotes: 0

Related Questions