C / C ++ strptime () does not parse% Z Timezone name

I am new to C. When I practice C, to hide the time before building tm back and forth. I noticed some difference. Please advise what I did wrong.

#include <string.h> #include <stdio.h> #include <time.h> /* test different format string to strptime " %A, %b %d, %X %z %Y " " %A, %b %d, %X %Z %Y " */ int main(int argc,char *argv[]) { char date[] = "6 Mar 2001 12:33:45"; char fmt[80]; struct tm tm; if (argc==1) return 0; strcpy(fmt,argv[1]); memset(&tm, 0, sizeof(struct tm)); if (strptime(date,"%d %b %Y %H:%M:%S",&tm)==NULL) printf("error\n"); char buf[128]; strftime(buf, sizeof(buf), fmt, &tm); printf("%s\n", buf); printf("%d\n", tm.tm_isdst); if (strptime(buf,fmt,&tm)==NULL) printf("error\n"); else { 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); } return 0; } 

When I use "% A,% b% d,% X% z% Y" as an argument to the conversion format, the code gives the following result:

  ~/user$ ./test_time " %A, %b %d, %X %z %Y " Tuesday, Mar 06, 12:33:45 +0000 2001 0 year: 101; month: 2; day: 6; hour: 12; minute: 33; second: 45 week day: 2; year day: 64 

When I change the argument to "% A,% b% d,% X% Z% Y", the code cannot parse the time string generated by strftime with exactly the same format.

  ~/user$ ./test_time " %A, %b %d, %X %Z %Y " Tuesday, Mar 06, 12:33:45 EET 2001 0 error 

Have I really missed something to let strptime correctly divulge timezone names?

Thanks in advance,

Albert

+4
source share
1 answer

I'm not sure that you will work. The glibc source code on github has this to say on this:

 case 'Z': /* XXX How to handle this? */ break 

followed by a slightly more "fleshy" processing of 'z' line files :-)

So, what is most likely happening here is that the line pointer does not move past EET when the format string is %Z , so when it tries to process %Y , it complains correctly that the EET invalid year. This is confirmed by the simple case "%%" , where the code really advances the rp input line pointer:

 case '%': /* Match the `%' character itself. */ match_char ('%', *rp++); break; 

The Linux manual page also points to extensions (of which 'z' is one):

For symmetry reasons, glibc tries to maintain strptime () the same format characters as strftime (3). (In most cases, the corresponding fields are analyzed, but no field in tm changes.)

Also, the state of GNU docs (italics mine):

% Z: The name of the time zone. Note. This is currently not fully implemented. The format is recognized, the input is consumed, but the tm field is not specified.

So, I really consider this a mistake, although it can be easily fixed by changing the documentation in order to stop pretending that it can handle Z time slots.

I can not find the corresponding error in bugzilla, so I raised the error on glibc. You can track it here .


Appendix: in accordance with the link to the error message in the previous paragraph and glibc 2.19 release , the change that I proposed was aligned with the documentation documentation. I hope there are no errors in this, or I will look pretty stupid if you consider only five lines of code.

+6
source

All Articles