This is the mail archive of the libc-help@sourceware.org mailing list for the glibc project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
Hi, I'm trying to parse date/time strings which look like: 2009-04-14T13:00:00 CEST 2009-04-14T13:00:00+0 2009-04-14T13:00:00+Z 2009-04-14T13:00:00CEST 2009-04-14T13:00:00 CET You get the idea. My questions: (Q1) Is strptime the right approach? (Q2) Does strptime help me with the timezone thing? My approach at the moment is (yes, it is awkward, so I guess I'm doing someething wrong): (1) parse the string first with "%FT%T%z" to see whether it "makes sense" strftime(datetime, "%FT%T%z", &tm); (2) re-parse it with ""%FT%T" to get hold of the time zone part char *tz = strftime(datetime, "%FT%T%z", &tm); (the return value of strftime should now point at (the beginning of) the assumed time zone part, right?) (3) Convert the whole struct tm to a time_t, whithin the time zone gathered in (2); that's achieved by temporarily setting the TZ environment variable to whatever timezone we have: char *oldtz = getenv("TZ"); if(tz && *tz) setenv("TZ", tz, 1); else setenv("TZ, "", 1); /* want UTC as default */ time_t tim = mktime(&tm); if(oldtz) setenv("TZ", oldtz, 1); else unsetenv("TZ"); (This raises te next question: (Q3) How does that work in multithreaded environments?) Needless to say, this doesn't always work: the timezone database has entries for CET (for example), but not for CEST (I'm on some vanilla GNU/Linux, more or less current Debian). Attached is a little test program which does roughly what I outlined above. Am I missing something? Am I better off cooking up something by myself? Thanks a million for any hints Regards -- tomás
/* tform.c test bench for iso8601 transform */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <time.h> static char* localizetime(char *datetime, char *format); int main(int argc, char *argv[]) { switch(argc) { case 3: printf("%s\n", localizetime(argv[1], argv[2])); break; case 2: printf("%s\n", localizetime(argv[1], NULL)); break; default: printf("Usage: %s <datetime> [<output format>]\n", argv[0]); break; } } static char* localizetime(char *datetime, char *format){ struct tm tm_in; struct tm tm_out; time_t tim; static char timbuf[255]; /* CAREFUL */ memset(&tm_in, 0, sizeof(struct tm)); memset(&tm_out, 0, sizeof(struct tm)); /* if(!format) format = "%c"; */ format = "%F %T"; if(datetime) { /* parse */ char *rest = NULL; /* unparsed debris from strptime or target timezone */ char *oldtz = NULL; /* old timezone, for restore */ /* parse the given timestamp into a tm struct. Parse twice. Once with timezone, to check validity (debris must be empty)... */ rest = strptime(datetime, "%FT%T%z", &tm_in); if (rest && *rest) { /* some debris */ printf("zeit:format-iso-8601: Could not successfully parse ISO-8601 date '%s' -- unparsed '%s'\n", datetime, rest); goto FAIL; } /* ...and a second time without timezone (debris is now timezone) */ rest = strptime(datetime, "%FT%T", &tm_in); /* switch to this timezone: FIXME this is not thread safe! Cf. Linux manpage for timegm(3) for this shenanigan */ while(isspace(*rest)) rest++; printf(" timezone='%s'\n", rest); oldtz = getenv("TZ"); if(rest && *rest) setenv("TZ", rest, 1); else unsetenv("TZ"); tzset(); tim = mktime(&tm_in); if(oldtz) setenv("TZ", oldtz, 1); else unsetenv("TZ"); tzset(); } else { /* no date time: now */ tim = time(NULL); } /* to local time */ localtime_r(&tim, &tm_out); /* format tm struct according to format string passed in */ strftime(timbuf, sizeof(timbuf), format, &tm_out); return timbuf; FAIL: return "--"; }
Attachment:
sample
Description: Text document
Attachment:
signature.asc
Description: Digital signature
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |