3

When I run the following code strptime seems to ignore the timezone value. Just sets value of the local timezone (which is +10).

This is the output, (Running on Linux, compiled with gcc 4.6.3):

-----------2013-04-24T9:47:06+400 - %Y-%m-%dT%H:%M:%S%z
TM Break    H:9 is DST:0 GMT Off:0
The epoch value:    1366760826
DateTime in String:     04/24/13 - 09:47AM +1000

-----------2013-04-24T11:47:06+800 - %Y-%m-%dT%H:%M:%S%z
TM Break    H:11 is DST:0 GMT Off:36000
The epoch value:    1366768026
DateTime in String:     04/24/13 - 11:47AM +1000

-----------2013-04-24T9:47:06+0 - %Y-%m-%dT%H:%M:%S%z
TM Break    H:9 is DST:0 GMT Off:36000
The epoch value:    1366760826
DateTime in String:     04/24/13 - 09:47AM +1000

-----------2013-04-24T9:47:06+4 - %Y-%m-%dT%H:%M:%S%z
TM Break    H:9 is DST:0 GMT Off:36000
The epoch value:    1366760826
DateTime in String:     04/24/13 - 09:47AM +1000

This is the code:

void date_Test(){
    string dateStrings[] = {"2013-04-24T9:47:06+400"
                          , "2013-04-24T11:47:06+800"
                          , "2013-04-24T9:47:06+0"
                          , "2013-04-24T9:47:06+4"};
    string formatStrings[] = {"%Y-%m-%dT%H:%M:%S%z"
                            , "%Y-%m-%dT%H:%M:%S%z"
                            , "%Y-%m-%dT%H:%M:%S%z"
                            , "%Y-%m-%dT%H:%M:%S%z"};

process_Timezone(dateStrings, formatStrings);
}

void process_Timezone(string dateStrings[], string formatStrings[]){
    int num = 4; 

    for (int i = 0; i < num; i++) {
        cout << endl << "-----------" << dateStrings[i] << " - " << formatStrings[i] << endl;
        tm *dtm = new tm;
        strptime(dateStrings[i].c_str(), formatStrings[i].c_str(), dtm);
        cout << "TM Break \tH:" << dtm->tm_hour << " is DST:" << dtm->tm_isdst << " GMT Off:"  << dtm->tm_gmtoff << endl;
        time_t ep_dt = mktime(dtm);
        cout << "The epoch value: \t" << ep_dt << endl;
        char buffer[40];
        strftime(buffer, 40,"%x - %I:%M%p %z", dtm);
        cout << "DateTime in String: \t" << buffer << endl;
        delete dtm;
    }
}
pt123
  • 2,146
  • 1
  • 32
  • 57

3 Answers3

3

According to http://en.wikipedia.org/wiki/ISO_8601 your one and three digit timezone offsets are not valid ISO 8601 values (the form used by strptime at least on Linux), which requires hh[:][mm] as the format.

Mark B
  • 95,107
  • 10
  • 109
  • 188
  • I have tried variations like 0400, 04:00 none of them have worked, could not find even an example online of someone using it – pt123 Jul 23 '13 at 06:41
  • 1
    hey any luck on this, i have the same problem .. how create time_t from string having timezone – N3Xg3N Jan 09 '14 at 18:09
2

Might be late, but strptime does correctly parse the %z specifier, it stores it in tm.tm_gmtoff variable. This variable is not in the standard, but a gnu extension. mktime does not make use of this variable.

You can try

strptime(<time_string>, dtm);
std::cout << dtm->tm_gmtoff;

to see the parsed time offset.

Note .tm_gmtoff is in second, so to get the correct epoch time, you can do

auto offset = dtm->tm_gmtoff;
auto _epoch = mktime(dtm);
auto final_epoch = _epoch + offset

Sources

  • 1
    This helped me, so have an upvote, but I don't think it's quite right unless you're running in UTC. To explain why, I needed more space than a comment, so submitted my own answer. – Martin Dorey Sep 02 '21 at 11:59
2

The answer from @Nguyen Ha Kien helped me, but to get the right epoch time, I needed to factor in my local UTC offset too, after it's been filled in by mktime, and not override libc's determination of whether DST was active at the specified time here:

        int offset = dtm->tm_gmtoff;
        // Ask libc to work out whether the local timezone is in DST at this time.
        dtm->tm_isdst = -1;
        time_t ep_dt = mktime(dtm);
        ep_dt -= offset - dtm->tm_gmtoff;

int rather than auto just because I'm compiling on a 2011 era setup, hopefully like that used by pt123 originally, to show that the answer from Mark B gets strptime to parse tm_gmtoff for me:

(ia32)martind@sirius:~/playpen$ ls /lib/libc-2.11.3.so 
/lib/libc-2.11.3.so
(ia32)martind@sirius:~/playpen$ gcc -v
...
gcc version 4.4.5 (Debian 4.4.5-8) 
(ia32)martind@sirius:~/playpen$ g++ c-strptime-ignores-timezone-when-parsing.cpp 
(ia32)martind@sirius:~/playpen$ ./a.out

-----------2013-04-24T9:47:06+0400 - %Y-%m-%dT%H:%M:%S%z
TM Break    H:9 is DST:0 GMT Off:14400

The only additional code was:

#include <iostream>
#include <string>

using namespace std;

void process_Timezone(string dateStrings[], string formatStrings[]);
void date_Test();
int main(){
    date_Test();
}
Martin Dorey
  • 2,944
  • 2
  • 24
  • 16