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
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
QString input = input_;
00358
00359
00360
int tPos = input.find(
'T');
00361
00362
00363
00364
if (-1 == tPos) {
00365
const int dashes = input.contains(
'-');
00366
if (0 == dashes) {
00367 input +=
"-01-01";
00368 }
else if (1 == dashes) {
00369 input +=
"-01";
00370 }
00371 tPos = input.length();
00372 input +=
"T12:00:00";
00373 }
00374
00375
00376
00377
QString dateString = input.left(tPos).stripWhiteSpace();
00378
00379
QString timeString = input.mid(tPos + 1).stripWhiteSpace();
00380
00381
QStringList l = QStringList::split(
'-', dateString);
00382
00383 year = l[0].toUInt();
00384 month = l[1].toUInt();
00385 mday = l[2].toUInt();
00386
00387
00388
if (
'Z' == timeString.at(timeString.length() - 1)) {
00389 timeString.remove(timeString.length() - 1, 1);
00390 }
00391
00392
00393
00394
int plusPos = timeString.findRev(
'+');
00395
00396
if (-1 != plusPos) {
00397
QString offsetString = timeString.mid(plusPos + 1);
00398
00399 offset = offsetString.left(2).toUInt() * 60 + offsetString.right(2).toUInt();
00400
00401 timeString = timeString.left(plusPos);
00402 }
else {
00403
int minusPos = timeString.findRev(
'-');
00404
00405
if (-1 != minusPos) {
00406
QString offsetString = timeString.mid(minusPos + 1);
00407
00408 offset = - int(offsetString.left(2).toUInt() * 60 + offsetString.right(2).toUInt());
00409
00410 timeString = timeString.left(minusPos);
00411 }
00412 }
00413
00414
00415
int dotPos = timeString.findRev(
'.');
00416
00417
if (-1 != dotPos) {
00418 timeString = timeString.left(dotPos);
00419 }
00420
00421
00422
00423 l = QStringList::split(
':', timeString);
00424
00425 hour = l[0].toUInt();
00426 min = l[1].toUInt();
00427 sec = l[2].toUInt();
00428
00429 time_t result = ymdhms_to_seconds(year, month, mday, hour, min, sec);
00430
00431
00432
if ((offset > 0) && (offset > result))
00433 offset = 0;
00434
00435 result -= offset*60;
00436
00437
00438
00439
00440
if (result < 1) result = 1;
00441
00442
return result;
00443 }
00444
00445
00446 int KRFCDate::localUTCOffset()
00447 {
00448 time_t timeNow = time((time_t*) 0);
00449
00450 tm *tM = gmtime(&timeNow);
00451
unsigned int timeUTC = ymdhms_to_seconds(tM->tm_year+1900, tM->tm_mon+1, tM->tm_mday,
00452 tM->tm_hour, tM->tm_min, tM->tm_sec);
00453
00454 tM = localtime(&timeNow);
00455
unsigned int timeLocal = ymdhms_to_seconds(tM->tm_year+1900, tM->tm_mon+1, tM->tm_mday,
00456 tM->tm_hour, tM->tm_min, tM->tm_sec);
00457
00458
return ((
int)(timeLocal-timeUTC))/60;
00459 }
00460
00461
00462
static const char *
const day_names[] = {
00463
"Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat"
00464 };
00465
00466
static const char *
const month_names[] = {
00467
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
00468
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
00469 };
00470
00471
00472 QCString KRFCDate::rfc2822DateString(time_t utcTime,
int utcOffset)
00473 {
00474 utcTime += utcOffset * 60;
00475 tm *tM = gmtime(&utcTime);
00476
char sgn = (utcOffset < 0) ?
'-' :
'+';
00477
int z = (utcOffset < 0) ? -utcOffset : utcOffset;
00478
QCString dateStr;
00479
00480 dateStr.sprintf(
"%s, %02d %s %04d %02d:%02d:%02d %c%02d%02d",
00481 day_names[tM->tm_wday], tM->tm_mday,
00482 month_names[tM->tm_mon], tM->tm_year+1900,
00483 tM->tm_hour, tM->tm_min, tM->tm_sec,
00484 sgn, z/60%24, z%60);
00485
00486
return dateStr;
00487 }
00488
00489
00490 QCString KRFCDate::rfc2822DateString(time_t utcTime)
00491 {
00492
return rfc2822DateString(utcTime,
localUTCOffset());
00493 }