00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <config.h>
00025
00026 #include <sys/param.h>
00027 #include <ctype.h>
00028 #include <stdlib.h>
00029
00030 #include <qstringlist.h>
00031
00032 #include <krfcdate.h>
00033
00034 static unsigned int ymdhms_to_seconds(int year, int mon, int day, int hour, int minute, int second)
00035 {
00036 if (sizeof(time_t) == 4)
00037 {
00038 if ((time_t)-1 < 0)
00039 {
00040 if (year >= 2038)
00041 {
00042 year = 2038;
00043 mon = 0;
00044 day = 1;
00045 hour = 0;
00046 minute = 0;
00047 second = 0;
00048 }
00049 }
00050 else
00051 {
00052 if (year >= 2115)
00053 {
00054 year = 2115;
00055 mon = 0;
00056 day = 1;
00057 hour = 0;
00058 minute = 0;
00059 second = 0;
00060 }
00061 }
00062 }
00063
00064 unsigned int ret = (day - 32075)
00065 + 1461L * (year + 4800L + (mon - 14) / 12) / 4
00066 + 367 * (mon - 2 - (mon - 14) / 12 * 12) / 12
00067 - 3 * ((year + 4900L + (mon - 14) / 12) / 100) / 4
00068 - 2440588;
00069 ret = 24*ret + hour;
00070 ret = 60*ret + minute;
00071 ret = 60*ret + second;
00072
00073 return ret;
00074 }
00075
00076 static const char haystack[37]="janfebmaraprmayjunjulaugsepoctnovdec";
00077
00078
00079
00080 static const struct {
00081 const char *tzName;
00082 int tzOffset;
00083 } known_zones[] = {
00084 { "UT", 0 },
00085 { "GMT", 0 },
00086 { "EST", -300 },
00087 { "EDT", -240 },
00088 { "CST", -360 },
00089 { "CDT", -300 },
00090 { "MST", -420 },
00091 { "MDT", -360 },
00092 { "PST", -480 },
00093 { "PDT", -420 },
00094 { 0, 0 }
00095 };
00096
00097 time_t
00098 KRFCDate::parseDate(const QString &_date)
00099 {
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 time_t result = 0;
00112 int offset = 0;
00113 char *newPosStr;
00114 const char *dateString = _date.latin1();
00115 int day = 0;
00116 char monthStr[4];
00117 int month = -1;
00118 int year = 0;
00119 int hour = 0;
00120 int minute = 0;
00121 int second = 0;
00122
00123
00124 while(*dateString && isspace(*dateString))
00125 dateString++;
00126
00127
00128 while(*dateString && !isdigit(*dateString) && !isspace(*dateString))
00129 dateString++;
00130
00131
00132 while(*dateString && isspace(*dateString))
00133 dateString++;
00134
00135 if (!*dateString)
00136 return result;
00137
00138 if (isalpha(*dateString))
00139 {
00140
00141
00142 while(*dateString && isspace(*dateString))
00143 dateString++;
00144
00145 for(int i=0; i < 3;i++)
00146 {
00147 if (!*dateString || (*dateString == '-') || isspace(*dateString))
00148 return result;
00149 monthStr[i] = tolower(*dateString++);
00150 }
00151 monthStr[3] = '\0';
00152
00153 newPosStr = (char*)strstr(haystack, monthStr);
00154
00155 if (!newPosStr)
00156 return result;
00157
00158 month = (newPosStr-haystack)/3;
00159
00160 if ((month < 0) || (month > 11))
00161 return result;
00162
00163 while (*dateString && isalpha(*dateString))
00164 dateString++;
00165 }
00166
00167
00168
00169 day = strtol(dateString, &newPosStr, 10);
00170 dateString = newPosStr;
00171
00172 if ((day < 1) || (day > 31))
00173 return result;
00174
00175 if (!*dateString)
00176 return result;
00177
00178 while(*dateString && (isspace(*dateString) || (*dateString == '-')))
00179 dateString++;
00180
00181 if (month == -1)
00182 {
00183 for(int i=0; i < 3;i++)
00184 {
00185 if (!*dateString || (*dateString == '-') || isspace(*dateString))
00186 return result;
00187 monthStr[i] = tolower(*dateString++);
00188 }
00189 monthStr[3] = '\0';
00190
00191 newPosStr = (char*)strstr(haystack, monthStr);
00192
00193 if (!newPosStr)
00194 return result;
00195
00196 month = (newPosStr-haystack)/3;
00197
00198 if ((month < 0) || (month > 11))
00199 return result;
00200
00201 while (*dateString && isalpha(*dateString))
00202 dateString++;
00203
00204 }
00205
00206
00207 while(*dateString && (isspace(*dateString) || (*dateString == '-')))
00208 dateString++;
00209
00210 if (!*dateString || !isdigit(*dateString))
00211 return result;
00212
00213
00214 year = strtol(dateString, &newPosStr, 10);
00215 dateString = newPosStr;
00216
00217
00218 if ((year >= 0) && (year < 50))
00219 year += 2000;
00220
00221 if ((year >= 50) && (year < 100))
00222 year += 1900;
00223
00224 if ((year < 1900) || (year > 2500))
00225 return result;
00226
00227
00228 if (*dateString)
00229 {
00230
00231 if (!isspace(*dateString++))
00232 return result;
00233
00234 hour = strtol(dateString, &newPosStr, 10);
00235 dateString = newPosStr;
00236
00237 if ((hour < 0) || (hour > 23))
00238 return result;
00239
00240 if (!*dateString)
00241 return result;
00242
00243
00244 if (*dateString++ != ':')
00245 return result;
00246
00247 minute = strtol(dateString, &newPosStr, 10);
00248 dateString = newPosStr;
00249
00250 if ((minute < 0) || (minute > 59))
00251 return result;
00252
00253 if (!*dateString)
00254 return result;
00255
00256
00257 if (*dateString != ':' && !isspace(*dateString))
00258 return result;
00259
00260
00261 if (*dateString ==':') {
00262 dateString++;
00263
00264 second = strtol(dateString, &newPosStr, 10);
00265 dateString = newPosStr;
00266
00267 if ((second < 0) || (second > 59))
00268 return result;
00269 } else {
00270 dateString++;
00271 }
00272
00273 while(*dateString && isspace(*dateString))
00274 dateString++;
00275 }
00276
00277
00278
00279 if (*dateString) {
00280 if ((strncasecmp(dateString, "gmt", 3) == 0) ||
00281 (strncasecmp(dateString, "utc", 3) == 0))
00282 {
00283 dateString += 3;
00284 while(*dateString && isspace(*dateString))
00285 dateString++;
00286 }
00287
00288 if ((*dateString == '+') || (*dateString == '-')) {
00289 offset = strtol(dateString, &newPosStr, 10);
00290 if (abs(offset) < 30)
00291 {
00292 dateString = newPosStr;
00293
00294 offset = offset * 100;
00295
00296 if (*dateString && *(dateString+1))
00297 {
00298 dateString++;
00299 int minutes = strtol(dateString, &newPosStr, 10);
00300 if (offset > 0)
00301 offset += minutes;
00302 else
00303 offset -= minutes;
00304 }
00305 }
00306
00307 if ((offset < -9959) || (offset > 9959))
00308 return result;
00309
00310 int sgn = (offset < 0)? -1:1;
00311 offset = abs(offset);
00312 offset = ((offset / 100)*60 + (offset % 100))*sgn;
00313 } else {
00314 for (int i=0; known_zones[i].tzName != 0; i++) {
00315 if (0 == strncasecmp(dateString, known_zones[i].tzName, strlen(known_zones[i].tzName))) {
00316 offset = known_zones[i].tzOffset;
00317 break;
00318 }
00319 }
00320 }
00321 }
00322
00323 result = ymdhms_to_seconds(year, month+1, day, hour, minute, second);
00324
00325
00326 if ((offset > 0) && (offset > result))
00327 offset = 0;
00328
00329 result -= offset*60;
00330
00331
00332
00333
00334 if (result < 1) result = 1;
00335
00336 return result;
00337 }
00338
00339 time_t
00340 KRFCDate::parseDateISO8601( const QString& input)
00341 {
00342
00343
00344
00345
00346
00347
00348 unsigned int year = 0;
00349 unsigned int month = 0;
00350 unsigned int mday = 0;
00351 unsigned int hour = 0;
00352 unsigned int min = 0;
00353 unsigned int sec = 0;
00354
00355 int offset = 0;
00356
00357
00358 int tPos = input.find('T');
00359
00360 if (-1 == tPos)
00361 return 0;
00362
00363
00364
00365 QString dateString = input.left(tPos).stripWhiteSpace();
00366
00367 QString timeString = input.mid(tPos + 1).stripWhiteSpace();
00368
00369 QStringList l = QStringList::split('-', dateString);
00370
00371 year = l[0].toUInt();
00372 month = l[1].toUInt();
00373 mday = l[2].toUInt();
00374
00375
00376 if ('Z' == timeString.at(timeString.length() - 1)) {
00377 timeString.remove(timeString.length() - 1, 1);
00378 }
00379
00380
00381
00382 int plusPos = timeString.findRev('+');
00383
00384 if (-1 != plusPos) {
00385 QString offsetString = timeString.mid(plusPos + 1);
00386
00387 offset = offsetString.left(2).toUInt() * 60 + offsetString.right(2).toUInt();
00388
00389 timeString = timeString.left(plusPos);
00390 } else {
00391 int minusPos = timeString.findRev('-');
00392
00393 if (-1 != minusPos) {
00394 QString offsetString = timeString.mid(minusPos + 1);
00395
00396 offset = - (offsetString.left(2).toUInt() * 60 + offsetString.right(2).toUInt());
00397
00398 timeString = timeString.left(minusPos);
00399 }
00400 }
00401
00402
00403 int dotPos = timeString.findRev('.');
00404
00405 if (-1 != dotPos) {
00406 timeString = timeString.left(dotPos);
00407 }
00408
00409
00410
00411 l = QStringList::split(':', timeString);
00412
00413 hour = l[0].toUInt();
00414 min = l[1].toUInt();
00415 sec = l[2].toUInt();
00416
00417 time_t result = ymdhms_to_seconds(year, month, mday, hour, min, sec);
00418
00419
00420 if ((offset > 0) && (offset > result))
00421 offset = 0;
00422
00423 result -= offset*60;
00424
00425
00426
00427
00428 if (result < 1) result = 1;
00429
00430 return result;
00431 }
00432
00433
00434 int KRFCDate::localUTCOffset()
00435 {
00436 time_t timeNow = time((time_t*) 0);
00437
00438 tm *tM = gmtime(&timeNow);
00439 unsigned int timeUTC = ymdhms_to_seconds(tM->tm_year+1900, tM->tm_mon+1, tM->tm_mday,
00440 tM->tm_hour, tM->tm_min, tM->tm_sec);
00441
00442 tM = localtime(&timeNow);
00443 unsigned int timeLocal = ymdhms_to_seconds(tM->tm_year+1900, tM->tm_mon+1, tM->tm_mday,
00444 tM->tm_hour, tM->tm_min, tM->tm_sec);
00445
00446 return ((int)(timeLocal-timeUTC))/60;
00447 }
00448
00449
00450 static const char * const day_names[] = {
00451 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
00452 };
00453
00454 static const char * const month_names[] = {
00455 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
00456 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
00457 };
00458
00459
00460 QCString KRFCDate::rfc2822DateString(time_t utcTime, int utcOffset)
00461 {
00462 utcTime += utcOffset * 60;
00463 tm *tM = gmtime(&utcTime);
00464 char sgn = (utcOffset < 0) ? '-' : '+';
00465 int z = (utcOffset < 0) ? -utcOffset : utcOffset;
00466 QCString dateStr;
00467
00468 dateStr.sprintf("%s, %02d %s %04d %02d:%02d:%02d %c%02d%02d",
00469 day_names[tM->tm_wday], tM->tm_mday,
00470 month_names[tM->tm_mon], tM->tm_year+1900,
00471 tM->tm_hour, tM->tm_min, tM->tm_sec,
00472 sgn, z/60%24, z%60);
00473
00474 return dateStr;
00475 }
00476
00477
00478 QCString KRFCDate::rfc2822DateString(time_t utcTime)
00479 {
00480 return rfc2822DateString(utcTime, localUTCOffset());
00481 }