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[4];
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,0,0 }, 0 }
00095 };
00096
00097 time_t
00098 KRFCDate::parseDate(const QString &_date)
00099 {
00100 if (_date.isEmpty())
00101 return 0;
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 time_t result = 0;
00115 int offset = 0;
00116 char *newPosStr;
00117 const char *dateString = _date.latin1();
00118 int day = 0;
00119 char monthStr[4];
00120 int month = -1;
00121 int year = 0;
00122 int hour = 0;
00123 int minute = 0;
00124 int second = 0;
00125
00126
00127 while(*dateString && isspace(*dateString))
00128 dateString++;
00129
00130
00131 while(*dateString && !isdigit(*dateString) && !isspace(*dateString))
00132 dateString++;
00133
00134
00135 while(*dateString && isspace(*dateString))
00136 dateString++;
00137
00138 if (!*dateString)
00139 return result;
00140
00141 if (isalpha(*dateString))
00142 {
00143
00144
00145 while(*dateString && isspace(*dateString))
00146 dateString++;
00147
00148 for(int i=0; i < 3;i++)
00149 {
00150 if (!*dateString || (*dateString == '-') || isspace(*dateString))
00151 return result;
00152 monthStr[i] = tolower(*dateString++);
00153 }
00154 monthStr[3] = '\0';
00155
00156 newPosStr = (char*)strstr(haystack, monthStr);
00157
00158 if (!newPosStr)
00159 return result;
00160
00161 month = (newPosStr-haystack)/3;
00162
00163 if ((month < 0) || (month > 11))
00164 return result;
00165
00166 while (*dateString && isalpha(*dateString))
00167 dateString++;
00168 }
00169
00170
00171
00172 day = strtol(dateString, &newPosStr, 10);
00173 dateString = newPosStr;
00174
00175 if ((day < 1) || (day > 31))
00176 return result;
00177
00178 if (!*dateString)
00179 return result;
00180
00181 while(*dateString && (isspace(*dateString) || (*dateString == '-')))
00182 dateString++;
00183
00184 if (month == -1)
00185 {
00186 for(int i=0; i < 3;i++)
00187 {
00188 if (!*dateString || (*dateString == '-') || isspace(*dateString))
00189 return result;
00190 monthStr[i] = tolower(*dateString++);
00191 }
00192 monthStr[3] = '\0';
00193
00194 newPosStr = (char*)strstr(haystack, monthStr);
00195
00196 if (!newPosStr)
00197 return result;
00198
00199 month = (newPosStr-haystack)/3;
00200
00201 if ((month < 0) || (month > 11))
00202 return result;
00203
00204 while (*dateString && isalpha(*dateString))
00205 dateString++;
00206
00207 }
00208
00209
00210 while(*dateString && (isspace(*dateString) || (*dateString == '-')))
00211 dateString++;
00212
00213 if (!*dateString || !isdigit(*dateString))
00214 return result;
00215
00216
00217 year = strtol(dateString, &newPosStr, 10);
00218 dateString = newPosStr;
00219
00220
00221 if ((year >= 0) && (year < 50))
00222 year += 2000;
00223
00224 if ((year >= 50) && (year < 100))
00225 year += 1900;
00226
00227 if ((year < 1900) || (year > 2500))
00228 return result;
00229
00230
00231 if (*dateString)
00232 {
00233
00234 if (!isspace(*dateString++))
00235 return result;
00236
00237 hour = strtol(dateString, &newPosStr, 10);
00238 dateString = newPosStr;
00239
00240 if ((hour < 0) || (hour > 23))
00241 return result;
00242
00243 if (!*dateString)
00244 return result;
00245
00246
00247 if (*dateString++ != ':')
00248 return result;
00249
00250 minute = strtol(dateString, &newPosStr, 10);
00251 dateString = newPosStr;
00252
00253 if ((minute < 0) || (minute > 59))
00254 return result;
00255
00256 if (!*dateString)
00257 return result;
00258
00259
00260 if (*dateString != ':' && !isspace(*dateString))
00261 return result;
00262
00263
00264 if (*dateString ==':') {
00265 dateString++;
00266
00267 second = strtol(dateString, &newPosStr, 10);
00268 dateString = newPosStr;
00269
00270 if ((second < 0) || (second > 59))
00271 return result;
00272 } else {
00273 dateString++;
00274 }
00275
00276 while(*dateString && isspace(*dateString))
00277 dateString++;
00278 }
00279
00280
00281
00282 if (*dateString) {
00283 if ((strncasecmp(dateString, "gmt", 3) == 0) ||
00284 (strncasecmp(dateString, "utc", 3) == 0))
00285 {
00286 dateString += 3;
00287 while(*dateString && isspace(*dateString))
00288 dateString++;
00289 }
00290
00291 if ((*dateString == '+') || (*dateString == '-')) {
00292 offset = strtol(dateString, &newPosStr, 10);
00293 if (abs(offset) < 30)
00294 {
00295 dateString = newPosStr;
00296
00297 offset = offset * 100;
00298
00299 if (*dateString && *(dateString+1))
00300 {
00301 dateString++;
00302 int minutes = strtol(dateString, &newPosStr, 10);
00303 if (offset > 0)
00304 offset += minutes;
00305 else
00306 offset -= minutes;
00307 }
00308 }
00309
00310 if ((offset < -9959) || (offset > 9959))
00311 return result;
00312
00313 int sgn = (offset < 0)? -1:1;
00314 offset = abs(offset);
00315 offset = ((offset / 100)*60 + (offset % 100))*sgn;
00316 } else {
00317 for (int i=0; known_zones[i].tzName != 0; i++) {
00318 if (0 == strncasecmp(dateString, known_zones[i].tzName, strlen(known_zones[i].tzName))) {
00319 offset = known_zones[i].tzOffset;
00320 break;
00321 }
00322 }
00323 }
00324 }
00325
00326 result = ymdhms_to_seconds(year, month+1, day, hour, minute, second);
00327
00328
00329 if ((offset > 0) && (offset > result))
00330 offset = 0;
00331
00332 result -= offset*60;
00333
00334
00335
00336
00337 if (result < 1) result = 1;
00338
00339 return result;
00340 }
00341
00342 time_t
00343 KRFCDate::parseDateISO8601( const QString& input_ )
00344 {
00345 if (input_.isEmpty())
00346 return 0;
00347
00348
00349
00350
00351
00352
00353
00354 unsigned int year = 0;
00355 unsigned int month = 0;
00356 unsigned int mday = 0;
00357 unsigned int hour = 0;
00358 unsigned int min = 0;
00359 unsigned int sec = 0;
00360
00361 int offset = 0;
00362
00363 QString input = input_;
00364
00365
00366 int tPos = input.find('T');
00367
00368
00369
00370 if (-1 == tPos) {
00371 const int dashes = input.contains('-');
00372 if (0 == dashes) {
00373 input += "-01-01";
00374 } else if (1 == dashes) {
00375 input += "-01";
00376 }
00377 tPos = input.length();
00378 input += "T12:00:00";
00379 }
00380
00381
00382
00383 QString dateString = input.left(tPos).stripWhiteSpace();
00384
00385 QString timeString = input.mid(tPos + 1).stripWhiteSpace();
00386
00387 QStringList l = QStringList::split('-', dateString);
00388
00389 if (l.size() < 3)
00390 return 0;
00391
00392 year = l[0].toUInt();
00393 month = l[1].toUInt();
00394 mday = l[2].toUInt();
00395
00396
00397 if ('Z' == timeString.at(timeString.length() - 1)) {
00398 timeString.remove(timeString.length() - 1, 1);
00399 }
00400
00401
00402
00403 int plusPos = timeString.findRev('+');
00404
00405 if (-1 != plusPos) {
00406 QString offsetString = timeString.mid(plusPos + 1);
00407
00408 offset = offsetString.left(2).toUInt() * 60 + offsetString.right(2).toUInt();
00409
00410 timeString = timeString.left(plusPos);
00411 } else {
00412 int minusPos = timeString.findRev('-');
00413
00414 if (-1 != minusPos) {
00415 QString offsetString = timeString.mid(minusPos + 1);
00416
00417 offset = - int(offsetString.left(2).toUInt() * 60 + offsetString.right(2).toUInt());
00418
00419 timeString = timeString.left(minusPos);
00420 }
00421 }
00422
00423
00424 int dotPos = timeString.findRev('.');
00425
00426 if (-1 != dotPos) {
00427 timeString = timeString.left(dotPos);
00428 }
00429
00430
00431
00432 l = QStringList::split(':', timeString);
00433
00434 if (l.size() < 3)
00435 return 0;
00436
00437 hour = l[0].toUInt();
00438 min = l[1].toUInt();
00439 sec = l[2].toUInt();
00440
00441 time_t result = ymdhms_to_seconds(year, month, mday, hour, min, sec);
00442
00443
00444 if ((offset > 0) && (offset > result))
00445 offset = 0;
00446
00447 result -= offset*60;
00448
00449
00450
00451
00452 if (result < 1) result = 1;
00453
00454 return result;
00455 }
00456
00457
00458 int KRFCDate::localUTCOffset()
00459 {
00460 time_t timeNow = time((time_t*) 0);
00461
00462 tm *tM = gmtime(&timeNow);
00463 unsigned int timeUTC = ymdhms_to_seconds(tM->tm_year+1900, tM->tm_mon+1, tM->tm_mday,
00464 tM->tm_hour, tM->tm_min, tM->tm_sec);
00465
00466 tM = localtime(&timeNow);
00467 unsigned int timeLocal = ymdhms_to_seconds(tM->tm_year+1900, tM->tm_mon+1, tM->tm_mday,
00468 tM->tm_hour, tM->tm_min, tM->tm_sec);
00469
00470 return ((int)(timeLocal-timeUTC))/60;
00471 }
00472
00473
00474 static const char * const day_names[] = {
00475 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
00476 };
00477
00478 static const char * const month_names[] = {
00479 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
00480 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
00481 };
00482
00483
00484 QCString KRFCDate::rfc2822DateString(time_t utcTime, int utcOffset)
00485 {
00486 utcTime += utcOffset * 60;
00487 tm *tM = gmtime(&utcTime);
00488 char sgn = (utcOffset < 0) ? '-' : '+';
00489 int z = (utcOffset < 0) ? -utcOffset : utcOffset;
00490 QCString dateStr;
00491
00492 dateStr.sprintf("%s, %02d %s %04d %02d:%02d:%02d %c%02d%02d",
00493 day_names[tM->tm_wday], tM->tm_mday,
00494 month_names[tM->tm_mon], tM->tm_year+1900,
00495 tM->tm_hour, tM->tm_min, tM->tm_sec,
00496 sgn, z/60%24, z%60);
00497
00498 return dateStr;
00499 }
00500
00501
00502 QCString KRFCDate::rfc2822DateString(time_t utcTime)
00503 {
00504 return rfc2822DateString(utcTime, localUTCOffset());
00505 }