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
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 }