Version: 1.8.3 (using KDE KDE 3.4.3) Installed from: Ubuntu Packages OS: Linux I regularly get email from someone with this type of header: Date: Wed, 7 Dec 2005 10:21:09 CET Kmail displays this time in the message index as 14:21. Both the sender and I are in the CET (+0100) time zone. It seems that kmail thinks that CET means -0300. I understand that this is not standard according to RFC2822. Therefore, according to RFC2822, this should be interpreted as +0000. Alternatively, it might be reasonable, for compatibility with certain older MUAs that generate this header, to interpret the time zone as +0100 (Central European Time). I do not see any reason for -0300. Note that this report is different from reports that merely complain about kmail interpreting weird time zones as +0000 .
SVN commit 494852 by mkoller: BUG:117848 Improve parsing of non-standard date strings. It now parses in addition date strings in the format "WWW MMM dd HH:MM:SS [Z] YYYY" zone is optional e.g.: Fri Oct 14 09:21:49 CEST 2005 or: Tue Mar 23 18:00:02 2004 M +3 -0 datetime.cpp M +103 -32 dw_date.cpp [POSSIBLY UNSAFE: scanf] --- branches/KDE/3.5/kdepim/mimelib/datetime.cpp #494851:494852 @@ -45,6 +45,7 @@ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; extern "C" int ParseRfc822Date(const char *str, struct tm *tms, int *z); +extern "C" int ParseDate(const char *str, struct tm *tms, int *z); static DwInt32 ymd_to_jdnl(int year, int mon, int day, int julian); static void jdnl_to_ymd(DwInt32 jdn, int *year, int *mon, int *day, int julian); static DwUint32 my_inv_gmtime(struct tm* ptms); @@ -282,6 +283,8 @@ struct tm tms; int zone; int err = ParseRfc822Date(str, &tms, &zone); + if ( err == -1 ) // try another format + err = ParseDate(str, &tms, &zone); if (!err) { mYear = tms.tm_year + 1900; mMonth = tms.tm_mon+1; --- branches/KDE/3.5/kdepim/mimelib/dw_date.cpp #494851:494852 @@ -526,10 +526,6 @@ if (str[pos+1] == 'T' || str[pos+1] == 't') { zone = 0; } - else { - /* Military time zone */ - zone = 480; - } break; case 'G': case 'g': @@ -537,10 +533,6 @@ && (str[pos+2] == 'T' || str[pos+2] == 't')) { zone = 0; } - else { - /* Military time zone */ - zone = -420; - } break; case 'E': case 'e': @@ -552,10 +544,6 @@ && (str[pos+2] == 'T' || str[pos+2] == 't')) { zone = -240; } - else { - /* Military time zone */ - zone = -300; - } break; case 'C': case 'c': @@ -567,10 +555,15 @@ && (str[pos+2] == 'T' || str[pos+2] == 't')) { zone = -300; } - else { - /* Military time zone */ - zone = -180; + else if ((str[pos+1] == 'E' || str[pos+1] == 'e') // allow non-RFC822 "CET" + && (str[pos+2] == 'T' || str[pos+2] == 't')) { + zone = 60; } + else if ((str[pos+1] == 'E' || str[pos+1] == 'e') // allow non-RFC822 "CEST" + && (str[pos+2] == 'S' || str[pos+2] == 's') + && (str[pos+3] == 'T' || str[pos+3] == 't')) { + zone = 120; + } break; case 'M': case 'm': @@ -582,10 +575,6 @@ && (str[pos+2] == 'T' || str[pos+2] == 't')) { zone = -360; } - else { - /* Military time zone */ - zone = -720; - } break; case 'P': case 'p': @@ -597,10 +586,6 @@ && (str[pos+2] == 'T' || str[pos+2] == 't')) { zone = -420; } - else { - /* Military time zone */ - zone = 180; - } break; case 'Z': /* Military time zone */ @@ -653,7 +638,16 @@ return isValid ? 0 : -1; } +const char* wdays[] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; +const char* months[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + + #ifdef DW_TESTING_DATEPARSER #include <stdio.h> @@ -664,15 +658,6 @@ "" }; -const char* wdays[] = { - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" -}; - -const char* months[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - int main() { struct tm *ptms, tms1, tms2; @@ -723,3 +708,89 @@ } #endif + +// try to parse a date/time string given in a format not +// correctly specified in RFC822 format +// Here we detect the following format: +// "WWW MMM dd HH:MM:SS [Z] YYYY" zone is optional +// e.g.: Fri Oct 14 09:21:49 CEST 2005 +// or: Tue Mar 23 18:00:02 2004 + +#include <string.h> +#include <stdio.h> + +#ifdef __cplusplus +extern "C" +#endif +int ParseDate(const char *str, struct tm *tms, int *z) +{ + if ( !str ) + return -1; + + size_t len = strlen(str); + + if ( len < 24 ) // at least "WWW MMM dd HH:MM:SS YYYY" + return -1; + + int day=1, month=0, year=1970, hour=0, minute=0, second=0, zone=0; + int i; + + for (i = 0; i < 7; i++) + if ( strncmp(str, wdays[i], 3) == 0 ) + break; + + if ( i == 7 ) + return -1; + + for (i = 0; i < 12; i++) + if ( strncmp(str+4, months[i], 3) == 0 ) + break; + + if ( i == 12 ) + return -1; + + month = i; + + if ( sscanf(str+8, "%d %d:%d:%d", &day, &hour, &minute, &second) != 4 ) + return -1; + + if ( isdigit(str[20]) ) { // year without zone info, as in ctime() + if ( sscanf(str+20, "%d", &year) != 1 ) + return -1; + } + else { + if ( sscanf(str+20, "%*s %d", &year) != 1 ) + return -1; + + if ( strncmp(str+20, "EST" , 3) == 0 ) zone = -5 * 60; + else if ( strncmp(str+20, "EDT" , 3) == 0 ) zone = -4 * 60; + else if ( strncmp(str+20, "CST" , 3) == 0 ) zone = -6 * 60; + else if ( strncmp(str+20, "CDT" , 3) == 0 ) zone = -5 * 60; + else if ( strncmp(str+20, "MST" , 3) == 0 ) zone = -7 * 60; + else if ( strncmp(str+20, "MDT" , 3) == 0 ) zone = -6 * 60; + else if ( strncmp(str+20, "PST" , 3) == 0 ) zone = -8 * 60; + else if ( strncmp(str+20, "PDT" , 3) == 0 ) zone = -7 * 60; + else if ( strncmp(str+20, "CET" , 3) == 0 ) zone = 60; + else if ( strncmp(str+20, "CEST", 4) == 0 ) zone = 120; + } + + if ( (day < 1) || (day > 31) || + (hour < 0) || (hour > 23) || + (minute < 0) || (minute > 59) || + (second < 0) || (second > 59) || + (year < 1900) ) + return -1; + + if ( tms ) { + tms->tm_year = year - 1900; + tms->tm_mon = month; + tms->tm_mday = day; + tms->tm_hour = hour; + tms->tm_min = minute; + tms->tm_sec = second; + } + + if ( z ) *z = zone; + + return 0; +}
*** Bug 115829 has been marked as a duplicate of this bug. ***