LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 09-18-2012, 01:59 AM   #1
cbaurand
LQ Newbie
 
Registered: Sep 2012
Posts: 6

Rep: Reputation: Disabled
problem with time zone change in c++


Hi all,

I have written a little function which can get the time zone value from a time zone name.
Here is the code:
Code:
   std::string getTimeZone(const std::string& zoneName)
    {
        struct tm *t1, *t2;
        time_t tm1, tm2;

        // LOCAL TIME (Europe/Zurich)
        tm1 = time(NULL);
        string tz = "TZ=";
        
        // set the new TZ value (TZ=zoneName)
        putenv((char *)(tz+zoneName).c_str());  
        
        // check
        envTz = getenv("TZ");
        if (envTz != NULL)
                cout << "TZ2 = "<<envTz<<endl; 
        
        long dtime = 0;

        // GMT time
        t2 = gmtime(&tm1);
        tm2 = mktime(t2);
        t1 = localtime(&tm1);
        dtime = (long)(tm1 - tm2);
        short min = (short)(abs(dtime) %3600/60);

        ostringstream os;
        os <<boost::format("%|0+3d|")%(short)(dtime/3600)<<":"<< boost::format("%|02|")%min;
        
        return os.str();
        
    }
Here is the main which calls the funcion :
Code:
int main(int	argc,char *	argv[])
{
    cout << "America/Denver : "<<getTimeZone("America/Denver")<<endl;
    cout << "America/Denver : "<<getTimeZone("America/Denver")<<endl;
    cout << "Indian/Comoro : " <<getTimeZone("Indian/Comoro")<<endl;
    cout << "Asia/Iran : " << getTimeZone("Asia/Iran")<<endl;;
    cout << "Canada/Atlantic : "<<getTimeZone("Canada/Atlantic")<<endl;
    
    return 0;

}
Result :
Code:
TZ2 = America/Denver
America/Denver : +01:00     <---- Problem
TZ2 = America/Denver
America/Denver : -07:00     <---- Same is correct !!!??!!
TZ2 = Indian/Comoro
Indian/Comoro : +03:00
TZ2 = Asia/Iran
Asia/Iran : +00:00
TZ2 = Canada/Atlantic
Canada/Atlantic : -04:00
As you can see, the first result is bad !

Any idea ?

Last edited by cbaurand; 09-18-2012 at 04:16 AM.
 
Old 09-18-2012, 03:57 AM   #2
Snark1994
Senior Member
 
Registered: Sep 2010
Distribution: Debian
Posts: 1,632
Blog Entries: 3

Rep: Reputation: 346Reputation: 346Reputation: 346Reputation: 346
Code:
   string getTimeZone(const string& zoneName){
...
        string tz = "TZ=";
        
        // set the new TZ value (TZ=zoneName)
        putenv((char *)(tz+zoneName).c_str());  
        
...
    }
I'm afraid you can't concatenate strings like that in C++. You want something like:

Code:
#include <sstream>
#include <string>

using namespace std;

string getTimeZone(const string& zoneName){
...
    stringstream ss;
    ss << "TZ=" << zoneName;
        
    putenv(ss.str().c_str());  
        
...
}
Hope this helps,
 
Old 09-18-2012, 04:16 AM   #3
cbaurand
LQ Newbie
 
Registered: Sep 2012
Posts: 6

Original Poster
Rep: Reputation: Disabled
You can concatenate two std::string without any problem....
It's not the problem here.
 
Old 09-18-2012, 05:36 AM   #4
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,838

Rep: Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308
just a question: what will happen if you change the values: only the first answer is not ok, or only this pecific TZ is not ok?
 
Old 09-18-2012, 05:49 AM   #5
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by cbaurand View Post
You can concatenate two std::string without any problem....
It's not the problem here.
Yes, you are correct... concatenating strings is possible using the + operator. However, your second statement is incorrect (the problem is with the usage of putenv()).

The putenv() function accepts a pointer to char (a string), which becomes part of the environment. In other words, it takes ownership of the pointer. You are passing pointer to char of a temporary object.

From the man-page:
Code:
DESCRIPTION
       The  putenv()  function adds or changes the value of environment variables.  The argument string is
       of the form name=value.  If name does not already exist in the environment, then string is added to
       the  environment.   If  name  does  exist,  then the value of name in the environment is changed to
       value.  The string pointed to by string becomes part of the environment,  so  altering  the  string
       changes the environment.
I've attempted to fix your code to the best of my ability, however valgrind complains whether I allocate on the heap using "new" or whether using the C function strdup(). Here's that code:
Code:
std::string getTimeZone(const std::string& zoneName)
{
    // set the new TZ value (TZ=zoneName)
    std::string tz = "TZ=" + zoneName;

/*
    char* env_tz = new char[tz.size() + 1];
    memcpy(env_tz, tz.c_str(), tz.size());
    env_tz[tz.size()] = '\0';
*/
    char* env_tz = strdup(tz.c_str());
    putenv(env_tz);

    // LOCAL TIME (Europe/Zurich)
    time_t tm1 = time(NULL);

    // GMT time
    struct tm* t2 = gmtime(&tm1);
    time_t tm2 = mktime(t2);
    localtime(&tm1);

    std::ostringstream os;
    long dtime = (long)(tm1 - tm2);
    short min = (short)(abs(dtime) % 3600/60);
    os << boost::format("%|0+3d|") % (short)(dtime / 3600) << ":" << boost::format("%|02|") % min;

    return os.str();
}

Last edited by dwhitney67; 09-18-2012 at 05:52 AM.
 
Old 09-18-2012, 06:04 AM   #6
Snark1994
Senior Member
 
Registered: Sep 2010
Distribution: Debian
Posts: 1,632
Blog Entries: 3

Rep: Reputation: 346Reputation: 346Reputation: 346Reputation: 346
Tell you what's irritating: when you spend your morning trying to work out what the heck is wrong with the code (sorry for my wrong pointer earlier) only to find dwhitney67's done it first *eyeroll* At least I now think I know a lot more about C's timezone functions...

(I jest, of course)

Last edited by Snark1994; 09-18-2012 at 06:05 AM.
 
Old 09-18-2012, 06:50 AM   #7
cbaurand
LQ Newbie
 
Registered: Sep 2012
Posts: 6

Original Poster
Rep: Reputation: Disabled
Thanks dwhitney67,

It seems to work "correctly" now. More one thing is bad now: the result for America/Denver should be -06:00. The function localtime() doesn't consider the Daylight Saving Time.
I need now investigate about that.
 
Old 09-18-2012, 07:16 AM   #8
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by cbaurand View Post
Thanks dwhitney67,

It seems to work "correctly" now. More one thing is bad now: the result for America/Denver should be -06:00. The function localtime() doesn't consider the Daylight Saving Time.
I need now investigate about that.
What value does the following report on your system? On my system, it reports that DST is 0 (which is correct). Maybe it is coincidence that it works. I was always under the impression that Linux developers gave up on trying to support DST readings because it changes often (by governments).
Code:
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <string>
#include <iostream>

int main()
{
    std::string timezone = "TZ=America/New York";

    char* env_tz = strdup(timezone.c_str());

    putenv(env_tz);

    time_t theTime = time(0);

    struct tm* theTimeTM = localtime(&theTime);

    std::cout << "DST = " << theTimeTM->tm_isdst << std::endl;
}

Last edited by dwhitney67; 09-18-2012 at 07:18 AM.
 
Old 09-18-2012, 07:47 AM   #9
cbaurand
LQ Newbie
 
Registered: Sep 2012
Posts: 6

Original Poster
Rep: Reputation: Disabled
I got DST = 0.
After some investigations, i found that the problem comes from mktime. To avoid mismatch between winter and summer hour, just set the tm_isdst to -1.
It works fine now.

Thanks for all.
 
Old 09-18-2012, 07:54 AM   #10
cbaurand
LQ Newbie
 
Registered: Sep 2012
Posts: 6

Original Poster
Rep: Reputation: Disabled
Just for dwhitney67:
You've obtained DST=0 because "New York" is not recognised. Try "New_York". ;-)
 
Old 09-19-2012, 04:37 AM   #11
Snark1994
Senior Member
 
Registered: Sep 2010
Distribution: Debian
Posts: 1,632
Blog Entries: 3

Rep: Reputation: 346Reputation: 346Reputation: 346Reputation: 346
If you consider the problem solved, then please mark the thread 'SOLVED' (in thread tools, or a link at the top of the page) and mark any of dwhitney's posts that you found helpful as helpful

Thanks,
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
problem with time zone change in c++ cbaurand Linux - Newbie 1 09-18-2012 05:32 AM
change time zone ust Linux - Newbie 13 05-07-2010 09:45 PM
change NTP Time Zone eliufoo General 4 10-12-2008 05:52 AM
Change time zone procfs Linux - General 14 05-03-2006 10:16 PM
Time zone stuck in UTC - how to change? Ook Slackware 2 04-24-2005 10:55 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 06:53 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration