2

This small program reproduces the bug in my project. time_t variable is converted to struct_tm, then to string, and serialized to file. Later, this string is loaded from the file, and should be converted back to time_t. Resulting time_t differs from original by one hour (possibly because of daylight saving time). I can change only deserialization part, because file format should remain unchanged.

#include "stdafx.h"
#include <iostream>
#include <string>
#include <time.h>

using namespace std;

string FormatDateTime(struct tm* time);
void Test();


int _tmain(int argc, _TCHAR* argv[])
{
    Test();
    return 0;
}


string FormatDateTime(struct tm* time)
{
    static const char* months[] =
    {
        "Jan", "Feb",  "Mar", "Apr", "May", "Jun",  "Jul", "Aug",  "Sep", "Oct",  "Nov", "Dec"
    };

    char s[30];
    const char* month;

    if ( time->tm_mon >= 0  &&  time->tm_mon < 12 )
    {
        month = months[time->tm_mon];
    }
    else
    {
        month = "??";
    }

    sprintf(s, "%d-%s-%02d %02d:%02d:%02d",
        time->tm_year + 1900,
        month,
        time->tm_mday,
        time->tm_hour,
        time->tm_min,
        time->tm_sec);

    return s;
}

void Test()
{
    // time_t variable is initialized with current time
    time_t t = time(NULL);

    // time_t variable is converted to struct tm and then to string
    struct tm* ptm = localtime(&t);

    char buffer[100];

    sprintf(buffer, "%d %d %d %d %d %d",
        ptm->tm_mday, ptm->tm_mon + 1, ptm->tm_year + 1900, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);

    cout << buffer << endl;         // string is OK


    // string is saved to the file

    // *********************************************************************************************

    // later this string is restored from the file

    // **** I can change something only after this line **** //

    struct tm stm;
    memset(&stm, 0, sizeof(stm));

    sscanf(buffer, "%d %d %d %d %d %d",
        &stm.tm_mday, &stm.tm_mon, &stm.tm_year, &stm.tm_hour, &stm.tm_min, &stm.tm_sec);

    stm.tm_mon -= 1;
    stm.tm_year -= 1900;

    string s = FormatDateTime(ptm);

    cout << s << endl;              // OK

    // *********************************************************************************************
    // Now I need to convert struct tm to time_t and keep it in the variable

    time_t t1 = mktime(&stm);       // not the same time - 1 hour difference

    if ( t1 == t )
    {
        cout << "t1 == t" << endl;
    }
    else
    {
        cout << "t1 != t   !!!!!" << endl;
    }

    // time_t is printed - result is incorrect

    // Utilities::FormatDateTime
    struct tm* ptm1 = localtime(&t1);

    s = FormatDateTime(ptm1);

    cout << s << endl;
}

Local time is 11.33. Result:

19 7 2012 11 33 17
2012-Jul-19 11:33:17
t1 != t   !!!!!
2012-Jul-19 12:33:17

How can I change the last part of this program to get correct result?

6
  • What's this: if ( time->tm_mon >= 0 && time->tm_mon tm_mon]; }? Commented Jul 19, 2012 at 8:35
  • @SingerOfTheFall - the question is edited. Commented Jul 19, 2012 at 8:42
  • Can't reproduce, it totally works for me: 19 7 2012 12 45 48 2012-Jul-19 12:45:48 t1 == t 2012-Jul-19 12:45:48 Commented Jul 19, 2012 at 8:46
  • @SingerOfTheFall maybe you are in another timezone so you don't notice it. Commented Jul 19, 2012 at 8:48
  • @SingerOfTheFall - can you tell me what is ptm->tm_isdst in your case? My guess is that it should be 0 (daylight saving time is not applied), in my case it is 1, since daylight saving is applied in my country. Commented Jul 19, 2012 at 9:29

2 Answers 2

4

my guess is that tm_isdst is different in your both tm structs. In one case its 0 and in the other 1.

Sign up to request clarification or add additional context in comments.

Comments

-1

That will not solve the probleme but for compatibility issues that might come later time 0 should represent january 1st 1970 and not 1900

1 Comment

If you are referring to the + 1900 in the source example, tm_year is defined as offset from 1900!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.