Link to home
Start Free TrialLog in
Avatar of Vlearns
Vlearns

asked on

strptime not recognizing timezone

#include <stdio.h>
#include <time.h>
#include <cstring>
#include <time.h>
int main() {
   char * p = "31-Dec-2002 22:36:36 -0800";
   time_t epoch;

   struct tm tm;

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

   // Epoch time 0
 /*
  date.tm_hour = -8;
   date.tm_mday = 1;
   date.tm_year = 1970 - 1900;
 */
epoch = mktime( &tm);
   printf(" Epoch = %d\n", epoch);

   if (strptime("31-Dec-2002 22:36:36 -0800", "%d-%b-%Y %H:%M:%S %Z", &tm)==NULL){printf( "error\n");}



printf("year: %d; month: %d; day: %d;\n",
        tm.tm_year, tm.tm_mon, tm.tm_mday);
printf("hour: %d; minute: %d; second: %d\n",
        tm.tm_hour, tm.tm_min, tm.tm_sec);
printf("week day: %d; year day: %d\n", tm.tm_wday, tm.tm_yday);


tm.tm_isdst = -1;
 /* Not set by strptime(); tells mktime()
                          to determine whether daylight saving time
                          is in effect */

  epoch = mktime( &tm);


   printf(p); printf("\n");
   printf(" Epoch = %d\n", epoch);
}

#include <stdio.h>
#include <time.h>
#include <cstring>
#include <time.h>
int main() {
   char * p = "31-Dec-2002 22:36:36 -0800";
   time_t epoch;

   struct tm tm;

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

   // Epoch time 0
 /*
  date.tm_hour = -8;
   date.tm_mday = 1;
   date.tm_year = 1970 - 1900;
 */
epoch = mktime( &tm);
   printf(" Epoch = %d\n", epoch);

   if (strptime("31-Dec-2002 22:36:36 -0800", "%d-%b-%Y %H:%M:%S %Z", &tm)==NULL){printf( "error\n");}



printf("year: %d; month: %d; day: %d;\n",
        tm.tm_year, tm.tm_mon, tm.tm_mday);
printf("hour: %d; minute: %d; second: %d\n",
        tm.tm_hour, tm.tm_min, tm.tm_sec);
printf("week day: %d; year day: %d\n", tm.tm_wday, tm.tm_yday);


tm.tm_isdst = -1;
 /* Not set by strptime(); tells mktime()
                          to determine whether daylight saving time
                          is in effect */

  epoch = mktime( &tm);


   printf(p); printf("\n");
   printf(" Epoch = %d\n", epoch);
}

Open in new window

Avatar of Vlearns
Vlearns

ASKER

hi in the code above


the time zone -0800 seems to be ignored by strptime, can some one help whats wrong or suggest any way by which i can correctly convert
"31-Dec-2002 22:36:36 -0800" to utc epoch time

thanks

%Z expects a timezone name (like "PDT") not an offset. See this link:

https://www.experts-exchange.com/expertsZone.jsp
Avatar of phoffric
Are you required to use strptime? It is not fully portable yet to other platforms. In fact, the %Z is under a category called GNU extension, which sounds like using %Z is even less portable even if strptime is supported.

See %z and %Z definition in strftime (strptime is supposed to use similar definitions):
http://linux.die.net/man/3/strftime

Here is another link that may assist:
https://www.experts-exchange.com/questions/24684311/How-do-I-stop-strptime-from-adjusting-for-timezone.html?sfQueryTermInfo=1+strptime

Avatar of Vlearns

ASKER

my bad understanding then


could you help change my code to use strftime instead of strptime..

i am finding the conversion a bit confusing

strftime seems to correctly handle offsets from the man page link
Someone else may have a solution in using strptime if you want to go that course.

Otherwise, I am thinking that you can use scanf or strtok to parse. I'll be back in a few hours to assist. In the meantime, why not take a stab at using scanf or strtok to start the process. Post your code, and we'll be happy to help.
Vlearns:
re: "change my code to use strftime instead of strptime"
strftime is an inverse function of strptime (at least that's what I recently learned, since my two platforms do not support strptime, and I never heard of it before). So, strftime yields an ascii string based on a formatting string that is described in http://linux.die.net/man/3/strftime. You are trying to go the other way around. You are starting with with a date/time string and are trying to get to an unix epoch time.

jb1dev,
The link you provided appears to be python related. Do you know if the python definition applies to the c-environment?
Avatar of Vlearns

ASKER

yes... any ideas????
I recommend whichever approach you either feel comfortable, or wish to learn about:
1. use scanf to parse
2. use strtok to parse and convert strings to atoi where applicable
3. parse using your own code, one char at a time
Please review the two functions. If you are taking a course, both of them are important to know about. (Granted, scanf does have some controversial issues - but not to worry at this time.)

Do you need help with designing the parsing? If so, we can talk it through. Give an approach, and I'll be happy to critique it. Or, if you have specific questions, I'll try to answer them.

Is this related to homework?
>> strptime not recognizing timezone

strptime could parse your timezone (with %Z or %z in gcc eg.), but it doesn't put it in the tm struct, because there's no timezone information in the tm struct.

Furthermore, proper handling of DST complicates things even more.

Parsing it manually, and adjusting for timezone and DST as needed seems the way to go.
Avatar of Vlearns

ASKER

hi

thank you all for the responses

" parsing it manually, and adjusting for timezone and DST as needed seems the way to go."

are you suggesting that we should not use tm struct?

or rather use the tm  struct and then add/subract time zone? can you point me to an example that does this?
>> are you suggesting that we should not use tm struct?

The tm struct can't account for timezone information. So if you wanted, you could use it, up to the moment you want to add the timezone offset.

You could fill up the tm struct with all information you have, then use mktime to get the seconds since the epoch (remember that this is in local time). Finally adjust that value with the timezone (relative to the local timezone) and DST information.

Or you could fill up the tm struct with all information you have, then adjust the tm struct members to take into account the timezone and DST information, and finally use mktime to calculate the seconds since the epoch (again remember that this is done in local time, so you need to adjust for that too).

The first approach looks easier.
Avatar of Vlearns

ASKER

You could fill up the tm struct with all information you have, then use mktime to get the seconds since the epoch (remember that this is in local time). Finally adjust that value with the timezone (relative to the local timezone) and DST information.


if i run the program i pasted above

 Epoch = 0
31-Dec-2002 22:36:36 -0800
 Epoch = 1041374196

the result above doesnot account for -8000

should i do a Epoch = 1041374196 - 0800 = 1041373396

if i put this resulting 1041373396 at http://www.epochconverter.com/ i get the result as


GMT: Tue, 31 Dec 2002 22:23:16 GMT
Your timezone: Tuesday, December 31, 2002 2:23:16 PM


which is not  the same as 1041374196

also i have entered the date  31-Dec-2002 22:36:36 on the website and found the resulting Epoch = 1041374196  which is same as the output of the program which tells us that the epoch time is correct (minus the timezone info -0800) how do i use -0800?

thanks






ASKER CERTIFIED SOLUTION
Avatar of Infinity08
Infinity08
Flag of Belgium image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>> I think it is important to know what epoch time you get when you plug in a struct tm date that corresponds to the start of the epoch (Jan 1, 1970 00:00:00). This will verify what your local time setting on your computer is. On two computers next to each other in the workplace, one might be set to GMT (aka zulu) time, and the other might be set to local time. Then if you run the same code on both systems, you will get different results, since the struct tm values are defined as the local time.

I've already deduced his local timezone in my previous post ;)
Let's see what happens if you alter your code as follows:
   memset( &tm, 0, sizeof(tm) );
   tm.tm_mday = 1;  // set to Jan
   tm.tm_year = 1970 - 1900; // set to first year of epoch
   epoch = mktime( &tm);
   printf(" Epoch 0 = %d\n", epoch);
oh, race conditions... :)
Avatar of Vlearns

ASKER

thanks for both the responses ,this clarifies my understanding

if i do not want to assume the time zone of my machine what should i do?

1) first adjust 1041370596 by adding 3600 (1 hour) to get it from the local timezone to the GMT timezone :

        1041370596 + 3600 = 1041374196

how do i adjust to gmtime programatically?
The code below shows the epoch time when my local time is Jan 1, 1970 00:00:00.

Here is my output:
 Epoch 0 = 18000

Notice that 18000/3600 = 5 (hours) which means that at 0000 hours here, it is 0500 GMT. This means that my local time is -0500 from GMT.

   struct tm tm;

   memset( &tm, 0, sizeof(tm) );
   tm.tm_mday = 1;  // set to Jan
   tm.tm_year = 1970 - 1900; // set to first year of epoch
   epoch = mktime( &tm);
   printf(" Epoch 0 = %d\n", epoch);

Open in new window

>> if i do not want to assume the time zone of my machine what should i do?

What I told you in http:#26115164 ;)

>> how do i adjust to gmtime programatically?

By adjusting for the local timezone. That's all you can do, because mktime works based on the local timezone. The alternative is not to use mktime, but then you have to implement the whole time calculation yourself.
Or maybe you meant : "How do I retrieve the local timezone ?" In that case, phoffric's previous post should help ;)
Avatar of Vlearns

ASKER


i have a formatted input  date  as

"31-Dec-2002 22:36:36 -0800 so like

"date"<space>"zone

where zone is defined as



zone            = ("+" / "-") 4DIGIT
                    ; Signed four-digit value of hhmm representing
                    ; hours and minutes east of Greenwich (that is,
                    ; the amount that the given time differs from
                    ; Universal Time).  Subtracting the timezone
                    ; from the given time will give the UT form.
                    ; The Universal Time zone is "+0000".

is there a easy way for me to convert the zone to 0000

31-Dec-2002 22:36:36  +0000

so that this date is universal time zone

now i can safely use strptime and mktime to get the epoch time ?
I'm a little confused about what you want; maybe a little tired, so please bear with me (I'm EST).

To recap, from http:#26114838 and http:#26115164, it appears that your platform's timezone is set to GMT time. I think -0800 is Pacific Standard Time. If that is where you are, then your computer clock gives a time that is 8 hours ahead of your local time (i.e., the time on your wrist watch). If this is incorrect info, let me know.

I also thought from the discussion that you were not going to use the %Z option, but rather adjust the GMT time after you used mktime.

Could you define a function signature with all the inputs necessary to fully characterize the problem you wish to solve; and all the outputs; and any assumptions about the platform's local time zone setting.

I assume that you have no problem parsing out the "-0800" from the input string,
    "31-Dec-2002 22:36:36 -0800".
And that you have no problem then computing the integer -8 (hours) from this substring. Is this correct?

I see that http:#26115164 provides a 2-step method to compute the epoch time, which you should verify to see if that meets your needs. But it appears that this approach does not use the %Z conversion that you would like to use. But if that approach does work for you, then is it necessary to use %Z?
>> is there a easy way for me to convert the zone to 0000

It's a lot more complicated to modify the string than to modify the seconds count. So, no ... the easiest way to do this would require you to use the same procedure discussed earlier (using mktime with timezone and DST adjustments) to get a time in GMT, then convert it back to a string, and then use strptime to get the time out of that string again (which you already had).

This, as you can see, is not easier than the procedure we've already explained to you. There's a reason we chose to explain that procedure - and that's because it's probably the best approach for you. Where is it that you have a problem with it ?