krfcdate.cpp

来自「konqueror3 embedded版本, KDE环境下的当家浏览器的嵌入式版」· C++ 代码 · 共 494 行

CPP
494
字号
/* * *  This file is part of the KDE libraries *  Copyright (c) 2000-2002 Waldo Bastian <bastian@kde.org> *                2002 Rik Hemsley <rik@kde.org> * * $Id: krfcdate.cpp 465272 2005-09-29 09:47:40Z mueller $ * *  This library is free software; you can redistribute it and/or *  modify it under the terms of the GNU Library General Public *  License version 2 as published by the Free Software Foundation. * *  This library is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *  Library General Public License for more details. * *  You should have received a copy of the GNU Library General Public License *  along with this library; see the file COPYING.LIB.  If not, write to *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *  Boston, MA 02110-1301, USA. **/#include <config.h>#include <sys/param.h>#include <ctype.h>#include <stdlib.h>#include <qstringlist.h>#include <krfcdate.h>static unsigned int ymdhms_to_seconds(int year, int mon, int day, int hour, int minute, int second){    if (sizeof(time_t) == 4)    {       if ((time_t)-1 < 0)       {          if (year >= 2038)          {             year = 2038;             mon = 0;             day = 1;             hour = 0;             minute = 0;             second = 0;          }       }       else       {          if (year >= 2115)          {             year = 2115;             mon = 0;             day = 1;             hour = 0;             minute = 0;             second = 0;          }       }    }    unsigned int ret = (day - 32075)       /* days */            + 1461L * (year + 4800L + (mon - 14) / 12) / 4            + 367 * (mon - 2 - (mon - 14) / 12 * 12) / 12            - 3 * ((year + 4900L + (mon - 14) / 12) / 100) / 4            - 2440588;    ret = 24*ret + hour;     /* hours   */    ret = 60*ret + minute;   /* minutes */    ret = 60*ret + second;   /* seconds */    return ret;}static const char haystack[37]="janfebmaraprmayjunjulaugsepoctnovdec";// we follow the recommendation of rfc2822 to consider all// obsolete time zones not listed here equivalent to "-0000"static const struct {    const char tzName[4];    int tzOffset;} known_zones[] = {    { "UT", 0 },    { "GMT", 0 },    { "EST", -300 },    { "EDT", -240 },    { "CST", -360 },    { "CDT", -300 },    { "MST", -420 },    { "MDT", -360 },    { "PST", -480 },    { "PDT", -420 },    { { 0,0,0,0 }, 0 }};time_tKRFCDate::parseDate(const QString &_date){     // This parse a date in the form:     //     Wednesday, 09-Nov-99 23:12:40 GMT     // or     //     Sat, 01-Jan-2000 08:00:00 GMT     // or     //     Sat, 01 Jan 2000 08:00:00 GMT     // or     //     01 Jan 99 22:00 +0100    (exceptions in rfc822/rfc2822)     //     // We ignore the weekday     //     time_t result = 0;     int offset = 0;     char *newPosStr;     const char *dateString = _date.latin1();     int day = 0;     char monthStr[4];     int month = -1;     int year = 0;     int hour = 0;     int minute = 0;     int second = 0;     // Strip leading space     while(*dateString && isspace(*dateString))     	dateString++;     // Strip weekday     while(*dateString && !isdigit(*dateString) && !isspace(*dateString))     	dateString++;     // Strip trailing space     while(*dateString && isspace(*dateString))     	dateString++;     if (!*dateString)     	return result;  // Invalid date     if (isalpha(*dateString))     {        // ' Nov 5 1994 18:15:30 GMT'        // Strip leading space        while(*dateString && isspace(*dateString))           dateString++;        for(int i=0; i < 3;i++)        {           if (!*dateString || (*dateString == '-') || isspace(*dateString))              return result;  // Invalid date           monthStr[i] = tolower(*dateString++);        }        monthStr[3] = '\0';        newPosStr = (char*)strstr(haystack, monthStr);        if (!newPosStr)           return result;  // Invalid date        month = (newPosStr-haystack)/3; // Jan=00, Feb=01, Mar=02, ..        if ((month < 0) || (month > 11))           return result;  // Invalid date        while (*dateString && isalpha(*dateString))           dateString++; // Skip rest of month-name     }     // ' 09-Nov-99 23:12:40 GMT'     // ' 5 1994 18:15:30 GMT'     day = strtol(dateString, &newPosStr, 10);     dateString = newPosStr;     if ((day < 1) || (day > 31))         return result; // Invalid date;     if (!*dateString)        return result;  // Invalid date     while(*dateString && (isspace(*dateString) || (*dateString == '-')))     	dateString++;     if (month == -1)     {        for(int i=0; i < 3;i++)        {           if (!*dateString || (*dateString == '-') || isspace(*dateString))              return result;  // Invalid date           monthStr[i] = tolower(*dateString++);        }        monthStr[3] = '\0';                newPosStr = (char*)strstr(haystack, monthStr);        if (!newPosStr)           return result;  // Invalid date        month = (newPosStr-haystack)/3; // Jan=00, Feb=01, Mar=02, ..        if ((month < 0) || (month > 11))           return result;  // Invalid date                   while (*dateString && isalpha(*dateString))           dateString++; // Skip rest of month-name                }     // '-99 23:12:40 GMT'     while(*dateString && (isspace(*dateString) || (*dateString == '-')))     	dateString++;     if (!*dateString || !isdigit(*dateString))     	return result;  // Invalid date     // '99 23:12:40 GMT'     year = strtol(dateString, &newPosStr, 10);     dateString = newPosStr;     // Y2K: Solve 2 digit years     if ((year >= 0) && (year < 50))         year += 2000;     if ((year >= 50) && (year < 100))         year += 1900;  // Y2K     if ((year < 1900) || (year > 2500))     	return result; // Invalid date     // Don't fail if the time is missing.     if (*dateString)     {        // ' 23:12:40 GMT'        if (!isspace(*dateString++))           return result;  // Invalid date        hour = strtol(dateString, &newPosStr, 10);        dateString = newPosStr;        if ((hour < 0) || (hour > 23))           return result; // Invalid date        if (!*dateString)           return result;  // Invalid date        // ':12:40 GMT'        if (*dateString++ != ':')           return result;  // Invalid date        minute = strtol(dateString, &newPosStr, 10);        dateString = newPosStr;        if ((minute < 0) || (minute > 59))           return result; // Invalid date        if (!*dateString)           return result;  // Invalid date        // ':40 GMT'        if (*dateString != ':' && !isspace(*dateString))           return result;  // Invalid date        // seconds are optional in rfc822 + rfc2822        if (*dateString ==':') {           dateString++;           second = strtol(dateString, &newPosStr, 10);           dateString = newPosStr;           if ((second < 0) || (second > 59))              return result; // Invalid date        } else {           dateString++;        }        while(*dateString && isspace(*dateString))           dateString++;     }     // don't fail if the time zone is missing, some     // broken mail-/news-clients omit the time zone     if (*dateString) {        if ((strncasecmp(dateString, "gmt", 3) == 0) ||            (strncasecmp(dateString, "utc", 3) == 0))        {           dateString += 3;           while(*dateString && isspace(*dateString))              dateString++;        }        if ((*dateString == '+') || (*dateString == '-')) {           offset = strtol(dateString, &newPosStr, 10);           if (abs(offset) < 30)           {              dateString = newPosStr;                            offset = offset * 100;                            if (*dateString && *(dateString+1))              {                 dateString++;                 int minutes = strtol(dateString, &newPosStr, 10);                 if (offset > 0)                    offset += minutes;                 else                    offset -= minutes;              }           }           if ((offset < -9959) || (offset > 9959))              return result; // Invalid date           int sgn = (offset < 0)? -1:1;           offset = abs(offset);           offset = ((offset / 100)*60 + (offset % 100))*sgn;        } else {           for (int i=0; known_zones[i].tzName != 0; i++) {              if (0 == strncasecmp(dateString, known_zones[i].tzName, strlen(known_zones[i].tzName))) {                 offset = known_zones[i].tzOffset;                 break;              }           }        }     }     result = ymdhms_to_seconds(year, month+1, day, hour, minute, second);     // avoid negative time values     if ((offset > 0) && (offset > result))        offset = 0;     result -= offset*60;     // If epoch 0 return epoch +1 which is Thu, 01-Jan-70 00:00:01 GMT     // This is so that parse error and valid epoch 0 return values won't     // be the same for sensitive applications...     if (result < 1) result = 1;     return result;}time_tKRFCDate::parseDateISO8601( const QString& input_ ){  // These dates look like this:  // YYYY-MM-DDTHH:MM:SS  // But they may also have 0, 1 or 2 suffixes.  // Suffix 1: .secfrac (fraction of second)  // Suffix 2: Either 'Z' or +zone or -zone, where zone is HHMM  unsigned int year     = 0;  unsigned int month    = 0;  unsigned int mday     = 0;  unsigned int hour     = 0;  unsigned int min      = 0;  unsigned int sec      = 0;  int offset = 0;  QString input = input_;  // First find the 'T' separator, if any.  int tPos = input.find('T');  // If there is no time, no month or no day specified, fill those missing  // fields so that 'input' matches YYYY-MM-DDTHH:MM:SS  if (-1 == tPos) {    const int dashes = input.contains('-');    if (0 == dashes) {      input += "-01-01";    } else if (1 == dashes) {      input += "-01";    }    tPos = input.length();    input += "T12:00:00";  }  // Now parse the date part.  QString dateString = input.left(tPos).stripWhiteSpace();  QString timeString = input.mid(tPos + 1).stripWhiteSpace();  QStringList l = QStringList::split('-', dateString);  year   = l[0].toUInt();  month  = l[1].toUInt();  mday   = l[2].toUInt();  // Z suffix means UTC.  if ('Z' == timeString.at(timeString.length() - 1)) {    timeString.remove(timeString.length() - 1, 1);  }  // +zone or -zone suffix (offset from UTC).  int plusPos = timeString.findRev('+');  if (-1 != plusPos) {    QString offsetString = timeString.mid(plusPos + 1);    offset = offsetString.left(2).toUInt() * 60 + offsetString.right(2).toUInt();    timeString = timeString.left(plusPos);  } else {    int minusPos = timeString.findRev('-');    if (-1 != minusPos) {      QString offsetString = timeString.mid(minusPos + 1);      offset = - int(offsetString.left(2).toUInt() * 60 + offsetString.right(2).toUInt());      timeString = timeString.left(minusPos);    }  }  // secfrac suffix.  int dotPos = timeString.findRev('.');  if (-1 != dotPos) {    timeString = timeString.left(dotPos);  }  // Now parse the time part.  l = QStringList::split(':', timeString);  hour   = l[0].toUInt();  min    = l[1].toUInt();  sec    = l[2].toUInt();  time_t result = ymdhms_to_seconds(year, month, mday, hour, min, sec);  // avoid negative time values  if ((offset > 0) && (offset > result))     offset = 0;  result -= offset*60;  // If epoch 0 return epoch +1 which is Thu, 01-Jan-70 00:00:01 GMT  // This is so that parse error and valid epoch 0 return values won't  // be the same for sensitive applications...  if (result < 1) result = 1;  return result;}int KRFCDate::localUTCOffset(){  time_t timeNow = time((time_t*) 0);  tm *tM = gmtime(&timeNow);  unsigned int timeUTC = ymdhms_to_seconds(tM->tm_year+1900, tM->tm_mon+1, tM->tm_mday,                                           tM->tm_hour, tM->tm_min, tM->tm_sec);  tM = localtime(&timeNow);  unsigned int timeLocal = ymdhms_to_seconds(tM->tm_year+1900, tM->tm_mon+1, tM->tm_mday,                                             tM->tm_hour, tM->tm_min, tM->tm_sec);  return ((int)(timeLocal-timeUTC))/60;}static const char * const day_names[] = {    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};static const char * const month_names[] = {    "Jan", "Feb", "Mar", "Apr", "May", "Jun",    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};QCString KRFCDate::rfc2822DateString(time_t utcTime, int utcOffset){    utcTime += utcOffset * 60;    tm *tM = gmtime(&utcTime);    char sgn = (utcOffset < 0) ? '-' : '+';    int z = (utcOffset < 0) ? -utcOffset : utcOffset;    QCString dateStr;    dateStr.sprintf("%s, %02d %s %04d %02d:%02d:%02d %c%02d%02d",                    day_names[tM->tm_wday], tM->tm_mday,                    month_names[tM->tm_mon], tM->tm_year+1900,                    tM->tm_hour, tM->tm_min, tM->tm_sec,                    sgn, z/60%24, z%60);    return dateStr;}QCString KRFCDate::rfc2822DateString(time_t utcTime){    return rfc2822DateString(utcTime, localUTCOffset());}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?