00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "k3rfcdate.h"
00022
00023 #include <config.h>
00024
00025 #include <sys/param.h>
00026 #include <ctype.h>
00027 #include <stdlib.h>
00028
00029 #include <QtCore/QMutableStringListIterator>
00030 #include <QtCore/QCharRef>
00031 #include <QtCore/QByteArray>
00032
00033 static unsigned int ymdhms_to_seconds(int year, int mon, int day, int hour, int minute, int second)
00034 {
00035 if (sizeof(time_t) == 4)
00036 {
00037 if ((time_t)-1 < 0)
00038 {
00039 if (year >= 2038)
00040 {
00041 year = 2038;
00042 mon = 0;
00043 day = 1;
00044 hour = 0;
00045 minute = 0;
00046 second = 0;
00047 }
00048 }
00049 else
00050 {
00051 if (year >= 2115)
00052 {
00053 year = 2115;
00054 mon = 0;
00055 day = 1;
00056 hour = 0;
00057 minute = 0;
00058 second = 0;
00059 }
00060 }
00061 }
00062
00063 unsigned int ret = (day - 32075)
00064 + 1461L * (year + 4800L + (mon - 14) / 12) / 4
00065 + 367 * (mon - 2 - (mon - 14) / 12 * 12) / 12
00066 - 3 * ((year + 4900L + (mon - 14) / 12) / 100) / 4
00067 - 2440588;
00068 ret = 24*ret + hour;
00069 ret = 60*ret + minute;
00070 ret = 60*ret + second;
00071
00072 return ret;
00073 }
00074
00075 static const char haystack[37]="janfebmaraprmayjunjulaugsepoctnovdec";
00076
00077
00078
00079 static const struct {
00080 const char tzName[4];
00081 int tzOffset;
00082 } known_zones[] = {
00083 { "UT", 0 },
00084 { "GMT", 0 },
00085 { "EST", -300 },
00086 { "EDT", -240 },
00087 { "CST", -360 },
00088 { "CDT", -300 },
00089 { "MST", -420 },
00090 { "MDT", -360 },
00091 { "PST", -480 },
00092 { "PDT", -420 },
00093 { { 0,0,0,0 }, 0 }
00094 };
00095
00096 time_t
00097 K3RFCDate::parseDate(const QString &_date)
00098 {
00099 if (_date.isEmpty())
00100 return 0;
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 time_t result = 0;
00114 int offset = 0;
00115 char *newPosStr;
00116 const QByteArray dateArray = _date.toLatin1();
00117 const char *dateString = dateArray.data();
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 K3RFCDate::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.indexOf(QLatin1Char('T'));
00367
00368
00369
00370 if (-1 == tPos) {
00371 const int dashes = input.count('-');
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).trimmed();
00384
00385 QString timeString = input.mid(tPos + 1).trimmed();
00386
00387 QStringList l = dateString.split( '-');
00388 if (l.size() < 3)
00389 return 0;
00390
00391 year = l[0].toUInt();
00392 month = l[1].toUInt();
00393 mday = l[2].toUInt();
00394
00395
00396 if ('Z' == timeString.at(timeString.length() - 1)) {
00397 timeString.remove(timeString.length() - 1, 1);
00398 }
00399
00400
00401
00402 int plusPos = timeString.lastIndexOf('+');
00403
00404 if (-1 != plusPos) {
00405 QString offsetString = timeString.mid(plusPos + 1);
00406
00407 offset = offsetString.left(2).toUInt() * 60 + offsetString.right(2).toUInt();
00408
00409 timeString = timeString.left(plusPos);
00410 } else {
00411 int minusPos = timeString.lastIndexOf('-');
00412
00413 if (-1 != minusPos) {
00414 QString offsetString = timeString.mid(minusPos + 1);
00415
00416 offset = - int(offsetString.left(2).toUInt() * 60 + offsetString.right(2).toUInt());
00417
00418 timeString = timeString.left(minusPos);
00419 }
00420 }
00421
00422
00423 int dotPos = timeString.lastIndexOf('.');
00424
00425 if (-1 != dotPos) {
00426 timeString = timeString.left(dotPos);
00427 }
00428
00429
00430
00431 l = timeString.split( ':');
00432 if (l.size() < 3)
00433 return 0;
00434
00435 hour = l[0].toUInt();
00436 min = l[1].toUInt();
00437 sec = l[2].toUInt();
00438
00439 time_t result = ymdhms_to_seconds(year, month, mday, hour, min, sec);
00440
00441
00442 if ((offset > 0) && (offset > result))
00443 offset = 0;
00444
00445 result -= offset*60;
00446
00447
00448
00449
00450 if (result < 1) result = 1;
00451
00452 return result;
00453 }
00454
00455
00456 int K3RFCDate::localUTCOffset()
00457 {
00458 time_t timeNow = time((time_t*) 0);
00459
00460 tm *tM = gmtime(&timeNow);
00461 unsigned int timeUTC = ymdhms_to_seconds(tM->tm_year+1900, tM->tm_mon+1, tM->tm_mday,
00462 tM->tm_hour, tM->tm_min, tM->tm_sec);
00463
00464 tM = localtime(&timeNow);
00465 unsigned int timeLocal = ymdhms_to_seconds(tM->tm_year+1900, tM->tm_mon+1, tM->tm_mday,
00466 tM->tm_hour, tM->tm_min, tM->tm_sec);
00467
00468 return ((int)(timeLocal-timeUTC))/60;
00469 }
00470
00471
00472 static const char day_names[][4] = {
00473 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
00474 };
00475
00476 static const char month_names[][4] = {
00477 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
00478 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
00479 };
00480
00481
00482 QByteArray K3RFCDate::rfc2822DateString(time_t utcTime, int utcOffset)
00483 {
00484 utcTime += utcOffset * 60;
00485 tm *tM = gmtime(&utcTime);
00486 char sgn = (utcOffset < 0) ? '-' : '+';
00487 int z = (utcOffset < 0) ? -utcOffset : utcOffset;
00488 QByteArray dateStr;
00489
00490 dateStr = QString().sprintf("%s, %02d %s %04d %02d:%02d:%02d %c%02d%02d",
00491 day_names[tM->tm_wday], tM->tm_mday,
00492 month_names[tM->tm_mon], tM->tm_year+1900,
00493 tM->tm_hour, tM->tm_min, tM->tm_sec,
00494 sgn, z/60%24, z%60).toAscii();
00495
00496 return dateStr;
00497 }