• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 274
  • Last Modified:

Another Date Question

I have 2 rows

row_elem[0]                           row_elem[1]

4/2/2002                                  4/1/2002     // monday
4/3/2002                                  4/1/2002

I want to test if row_elem[1] is monday, then add one day to row_elem[0]
so, the results should be
 
row_elem[0]
04032002
04042002

part of my code is the followings:

struct tm date = { 0 };  // row_elem[0]
struct tm date1 = { 0 }; // row_elem[1]

date.tm_mday = d;  // row_elem[0]
date1.tm_mday = d1; // row_elem[1]

date.tm_mon = m - 1; // row_elem[0]
date1.tm_mon = m1 - 1; // row_elem[1]

date.tm_year = Y - 1900; // row_elem[0]
date1.tm_year = Y1 - 1900; // row_elem[1]

time_t tt = mktime(&date); // row_elem[0]
time_t tt1 = mktime(&date1);  // row_elem[1]

struct tm* pDate = localtime(&tt); // row_elem[0]
struct tm* pDate1 = localtime(&tt1); // row_elem[1]

int wday = pDate->tm_wday; // 1 = monday, 2 = tuesday, ... // row_elem[0]
int wday1 = pDate1->tm_wday; // 1 = monday, 2 = tuesday, ... on row_elem[1]

date.tm_mday++; // works with 02292004 and 12312003 as well // row_elem[0]
date1.tm_mday++; // works with 02292004 and 12312003 as well // row_elem[1]

time_t ntt = mktime(&date); // row_elem[0]
time_t ntt1 = mktime(&date1); // row_elem[1]

struct tm* pNextDate = localtime(&ntt); // row_elem[0]
struct tm* pNextDate1 = localtime(&ntt1); // row_elem[1]

stringstream oss;
char szDate[10];
if ( wday1 == 1) // test if row_elem[1] is monday
{
    strftime(szDate,10,"%m%d%Y",pNextDate); // add one day tp row_elem[0]
    oss << szDate ;
   cout << oss.str().c_str() << endl;
}

I dont get the result I expect. It always adds one date to row_elem[1], not row_elem[0]

WHY?
0
justinY
Asked:
justinY
  • 10
  • 5
  • 3
  • +1
2 Solutions
 
justinYAuthor Commented:
also i have
int m = atoi(row_elem[0].substr(0, 2).c_str());
int d = atoi(row_elem[0].substr(2, 2).c_str());
int Y = atoi(row_elem[0].substr(4, 4).c_str());

int m1 = atoi(row_elem[1].substr(0, 2).c_str());
int d1 = atoi(row_elem[1].substr(2, 2).c_str());
int Y1 = atoi(row_elem[1].substr(4, 4).c_str());

0
 
gckcmcCommented:
can you put in all the code so we can compile and run it?
0
 
justinYAuthor Commented:
OK , here is my code
// I want to test sdate1=04012002, if sdate is monday, then add one day to sdate0, making it 04092002
int main()
{
string sdate0 = "04082002";
string sdate1 = "04012002";

stringstream oss1;

int m = atoi(sdate[0].substr(0, 2).c_str());
int d = atoi(sdate[0].substr(2, 2).c_str());
int Y = atoi(sdate[0].substr(4, 4).c_str());
//cout << d << endl;

int m1 = atoi(sdate[1].substr(0, 2).c_str());
int d1 = atoi(sdate[1].substr(2, 2).c_str());
int Y1 = atoi(sdate[1].substr(4, 4).c_str());


struct tm date = { 0 };
struct tm date1 = { 0 };

date.tm_mday = d;
date1.tm_mday = d1;
//cout << date.tm_mday << endl;

date.tm_mon = m - 1;
date1.tm_mon = m1 - 1;
//cout << date.tm_mon << endl;

date.tm_year = Y - 1900;
date1.tm_year = Y1 - 1900;

time_t tt = mktime(&date);
time_t tt1 = mktime(&date1);

struct tm* pDate = localtime(&tt);
struct tm* pDate1 = localtime(&tt1);


int wday = pDate->tm_wday; // 1 = monday, 2 = tuesday, ...
int wday1 = pDate1->tm_wday; // 1 = monday, 2 = tuesday, ...

date.tm_mday++;
date1.tm_mday++;

time_t ntt = mktime(&date);
time_t ntt1 = mktime(&date1);

struct tm* pNextDate = localtime(&ntt);
struct tm* pNextDate1 = localtime(&ntt1);

char szDate[10];

if ( wday1 == 1 )   // test if 04012002 is monday
{
      strftime(szDate,10,"%m%d%Y",pNextDate); // add one day to 04082002
      oss1 << szDate;
                cout << oss1.str().c_str() << endl;
}
else
{
      
      oss1 << sdate[0];
}
}
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
justinYAuthor Commented:
sorry, should be
sdate0 and sdate1 NOT sdate[0] and sdate[1]
0
 
efnCommented:
localtime doesn't give you a pointer to a new structure every time you call it.  It just has one structure that it uses over and over again.  So when you call localtime the second time, it writes over the data from the first call and gives you a pointer to the same structure again.  So pDate and pDate1 point to the same place, and that structure has data from the last call, the one that used tt1.  A solution is to make a copy of the structure after the first call to localtime and before the second call.
0
 
justinYAuthor Commented:
I am not sure 100% understood. Would you please modify my code, so I can learn from your modifications. thanks
0
 
efnCommented:
struct tm* pDate = localtime(&tt);

Now we want to save a copy of the structure addressed by pDate.  So we need to declare the copy.

struct tm Date;

We can copy the structure with an assignment statement.

Date = *pDate;

Now *pDate is about to get trashed, so subsequent code should use Date and not pDate.

Now there is really no need for pDate.  The three statements above could be condensed into this:

struct tm Date = *(localtime(&tt));
0
 
efnCommented:
Since you already have an identifer named "date", it would be better to pick a name other than "Date" for the structure where you store the copy.  (I just got Date by stripping off the 'p' prefix.)
0
 
justinYAuthor Commented:
Hi efn,

I still dont get it. It has the unexpected result. here is my revised code.

int main()
{
string sdate0 = "04012002";
string sdate1 = "04022002";

stringstream oss1;

int m = atoi(sdate0.substr(0, 2).c_str());
int d = atoi(sdate0.substr(2, 2).c_str());
int Y = atoi(sdate0.substr(4, 4).c_str());

int m1 = atoi(sdate1.substr(0, 2).c_str());
int d1 = atoi(sdate1.substr(2, 2).c_str());
int Y1 = atoi(sdate1.substr(4, 4).c_str());

struct tm date = { 0 };
struct tm date1 = { 0 };

date.tm_mday = d;
date1.tm_mday = d1;


date.tm_mon = m - 1;
date1.tm_mon = m1 - 1;

date.tm_year = Y - 1900;
date1.tm_year = Y1 - 1900;

time_t tt = mktime(&date);
time_t tt1 = mktime(&date1);

struct tm* pDate = localtime(&tt);
struct tm* cpDate = localtime(&tt);      // changed here
struct tm* pDate1 = localtime(&tt1);


int wday = cpDate->tm_wday; // 1 = monday, 2 = tuesday, ... // changed here
int wday1 = pDate1->tm_wday; // 1 = monday, 2 = tuesday, ...

date.tm_mday++;
date1.tm_mday++;

time_t ntt = mktime(&date);
time_t ntt1 = mktime(&date1);

struct tm* pNextDate = localtime(&ntt);
struct tm* pNextDate1 = localtime(&ntt1);

char szDate[10];

if ( wday == 1 )   // test if 04012002 is monday
{
     strftime(szDate,10,"%m%d%Y",pNextDate1); // add one day to 04022002
     oss1 << szDate;
                cout << oss1.str().c_str() << endl;
}
else
{
     
     oss1 << sdate[0];
}
}
0
 
efnCommented:
Do you understand why it's broken, but not how to fix it?  Or do you not understand why it's broken?  Do you think you understand pointers?
0
 
justinYAuthor Commented:
whats your point ?
If I understand everything, then I dont need to come here for your expertise.
0
 
efnCommented:
I don't want to write an explanation of something you already understand, nor of something basic that's already explained in many books and web sites.  If we can narrow down your difficulty in understanding my comments to something more specific than that you don't get it, I might be able to explain it so you can understand it.  So I asked some questions to try to gather specific information about what you do and don't understand.  If you don't want to go through that kind of tutorial process, that's fine, and maybe someone else here will be able to help you more effectively.
0
 
justinYAuthor Commented:
I think I got it right this time by changing the order of the followings. Thanks

struct tm* pDate = localtime(&tt);
struct tm* pDate1 = localtime(&tt1);
struct tm* cpDate = localtime(&tt);      // changed here

int wday = cpDate->tm_wday; // 1 = monday, 2 = tuesday, ... // changed here
int wday1 = pDate1->tm_wday; // 1 = monday, 2 = tuesday, ...
0
 
itsmeandnobodyelseCommented:
>> I think I got it right this time by changing the order

No, the second statement

     struct tm* pDate1 = localtime(&tt1);

overwrites the result where the pointer pDate is pointing to (actually pDate and pDate1 have the same pointer value) and the third statement  

    struct tm* cpDate = localtime(&tt);

overwrites the result where the pointer pDate1 is pointing to (again: pDate == pDate1 == cpDate).

The function localtime has only one static buffer to store results. localtime() returns a pointer to that buffer. If you are calling localtime() twice, the second call always overwrites the result of the previous call and the pointer you get is always the same. And it doesn't help you to store it to different pointer variables (pDate, pDate1, cpDate).

There are two ways out: First, you could evaluate (or print out) the results of a call to localtime() immediately after calling and *prior* to your next call to localtime. Second, you could make a local copy of the result (that is an instance of struct tm, *not* an instance of struct tm* ).

(First)

struct tm* pDate = localtime(&tt);
// evaluate pDate *before* next call to localtime
int wday = pDate->tm_wday; // 1 = monday, 2 = tuesday, ...

// The next statement overwrites the data where pDate points to
// i. e. pDate->tm_wday will be overwritten but not wday as wday is a local variable
struct tm* pDate1 = localtime(&tt1);
int wday1 = pDate1->tm_wday; // 1 = monday, 2 = tuesday, ...


(Second)

struct tm* pDate = localtime(&tt);
// Make a copy of the result
struct tm Date = *pDate;

struct tm* pDate1 = localtime(&tt1);

// First wday we take from saved copy
int wday =  Date.tm_wday; // 1 = monday, 2 = tuesday, ...

// Second wday1 we can take from pDate1 as it is valid while there is no
// further call to localtime()
int wday1 = pDate1->tm_wday; // 1 = monday, 2 = tuesday, ...


Regards, Alex

P.S.

If an expert asks you if you do unterstand it isn't to blame you, but to improve further explanations.
0
 
justinYAuthor Commented:
Hi Alex,
Your comments make perfect sense to me. And your revised code is working well.
But I run my error code. I have the same results I am looking for.
1. when I test sdate0 = 04012002, if its monday, then sdate1 is 04032002
2. when I test sdate0 = 04042002, if its not monday, then sdate1 keeps 04022002

So How can this happen ? I know my code is wrong, but why wrong code gives correct results ? Thanks for your help.
This is my wrong code:

int main()
{
string sdate0 = "04012002";
string sdate1 = "04022002";

stringstream oss1;

int m = atoi(sdate0.substr(0, 2).c_str());
int d = atoi(sdate0.substr(2, 2).c_str());
int Y = atoi(sdate0.substr(4, 4).c_str());

int m1 = atoi(sdate1.substr(0, 2).c_str());
int d1 = atoi(sdate1.substr(2, 2).c_str());
int Y1 = atoi(sdate1.substr(4, 4).c_str());

struct tm date = { 0 };
struct tm date1 = { 0 };

date.tm_mday = d;
date1.tm_mday = d1;


date.tm_mon = m - 1;
date1.tm_mon = m1 - 1;

date.tm_year = Y - 1900;
date1.tm_year = Y1 - 1900;

time_t tt = mktime(&date);
time_t tt1 = mktime(&date1);

struct tm* pDate = localtime(&tt);
struct tm* pDate1 = localtime(&tt1);
struct tm* cpDate = localtime(&tt);      // changed here

int wday = cpDate->tm_wday; // 1 = monday, 2 = tuesday, ... // changed here
int wday1 = pDate1->tm_wday; // 1 = monday, 2 = tuesday, ...

date.tm_mday++;
date1.tm_mday++;

time_t ntt = mktime(&date);
time_t ntt1 = mktime(&date1);

struct tm* pNextDate = localtime(&ntt);
struct tm* pNextDate1 = localtime(&ntt1);

char szDate[10];

if ( wday == 1 )   // test if 04012002 is monday
{
     strftime(szDate,10,"%m%d%Y",pNextDate1); // add one day to 04022002
     oss1 << szDate;
}
else
{
    oss1 << sdate1;
}
   cout << oss1.str().c_str() << endl;
}
0
 
itsmeandnobodyelseCommented:
>> struct tm* pDate = localtime(&tt);
>> struct tm* pDate1 = localtime(&tt1);
>> struct tm* cpDate = localtime(&tt);      // changed here

>> int wday = cpDate->tm_wday; // 1 = monday, 2 = tuesday, ... // changed here
>> int wday1 = pDate1->tm_wday; // 1 = monday, 2 = tuesday, ...

As i told you, you have to change that sequence to

   struct tm* pDate = localtime(&tt);
   int wday = pDate->tm_wday; //    NOTE, IT IS    pDate->tm_wday;
   struct tm* pDate1 = localtime(&tt1);
   int wday1 = pDate1->tm_wday; // 1 = monday, 2 = tuesday, ...

Please, read the answers we gave you. If you don't change your code, you'll never get a different result.

Regards, Alex


0
 
justinYAuthor Commented:
Alex, I think there is misunderstanding here.
I changed the code sequence and it is working well.
But the code I posted last time gives me the correct results too. I am just curious, why my error code gives correct result as your code does.
Sorry for the misunderstanding.
0
 
itsmeandnobodyelseCommented:
Justin, thank's for your comment because i couldn't believe that nothing had changed.

>> struct tm* cpDate = localtime(&tt);      // changed here

That statement overwrites the result of pDate1, but cpDate->tm_wday is valid. Therefore the next statement

     if ( wday == 1 )   // test if 04012002 is monday

is valid as well as  wday == cpDate->tm_wday.

wday1 would be wrong (actually it's equal to wday), but you don't use that variable. And you don't use (wrong) pDate1 neither. You are calling localtime again (twice) and this time pNextDate1 is the winner while (wrong) pNextDate wasn't evaluated. That's why

   if ( wday == 1 )

is correct in any case and

  strftime(szDate,10,"%m%d%Y",pNextDate1);

as well.

Regards, Alex

0
 
justinYAuthor Commented:
True, very true Alex,
Now I understand it. Thank you very much for your help.
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

  • 10
  • 5
  • 3
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now