• Skip to content
  • Skip to link menu
KDE 4.7 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KDECore

kdatetimeformatter.cpp
Go to the documentation of this file.
00001 /*
00002     Copyright 2009-2010 John Layt <john@layt.net>
00003     Copyright 2005-2010 David Jarvie <djarvie@kde.org>
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License as published by the Free Software Foundation; either
00008     version 2 of the License, or (at your option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014 
00015     You should have received a copy of the GNU Library General Public License
00016     along with this library; see the file COPYING.LIB.  If not, write to
00017     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018     Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "kdatetimeformatter_p.h"
00022 
00023 #include <QtCore/QDate>
00024 #include <QtCore/QString>
00025 #include <QtCore/QStringList>
00026 #include <QtCore/QChar>
00027 
00028 #include "kdatetime.h"
00029 #include "ktimezone.h"
00030 #include "kcalendarsystem.h"
00031 #include "kdayperiod_p.h"
00032 #include "klocale_p.h"
00033 #include "kdebug.h"
00034 
00035 KDateTimeFormatter::KDateTimeFormatter()
00036     : m_englishLocale(0),
00037       m_englishCalendar(0)
00038 {
00039 }
00040 
00041 KDateTimeFormatter::~KDateTimeFormatter()
00042 {
00043     delete m_englishCalendar;
00044     delete m_englishLocale;
00045 }
00046 
00047 QString KDateTimeFormatter::formatDate(const QDate &fromDate,
00048                                        const QString &toFormat,
00049                                        const KCalendarSystem *calendar,
00050                                        const KLocale *locale,
00051                                        KLocale::DigitSet digitSet,
00052                                        KLocale::DateTimeFormatStandard formatStandard) const
00053 {
00054     // If not valid input, don't waste our time
00055     if (!calendar->isValid(fromDate) || toFormat.isEmpty()) {
00056         return QString();
00057     }
00058 
00059     return formatDateTime(KDateTime(fromDate), toFormat, 0, calendar, locale, digitSet, formatStandard);
00060 }
00061 
00062 QString KDateTimeFormatter::formatTime(const QTime &fromTime,
00063                                        const QString &toFormat,
00064                                        KLocale::TimeFormatOptions timeOptions,
00065                                        const KCalendarSystem *calendar,
00066                                        const KLocale *locale,
00067                                        KLocale::DigitSet digitSet,
00068                                        KLocale::DateTimeFormatStandard formatStandard) const
00069 {
00070     // If not valid input, don't waste our time
00071     if (fromTime.isValid() || toFormat.isEmpty()) {
00072         return QString();
00073     }
00074 
00075     return formatDateTime(KDateTime(QDate::currentDate(), fromTime), toFormat, timeOptions, calendar, locale, digitSet, formatStandard);
00076 }
00077 
00078 // Format an input date to match a POSIX date format string
00079 QString KDateTimeFormatter::formatDateTime(const KDateTime &fromDateTime,
00080                                            const QString &toFormat,
00081                                            KLocale::TimeFormatOptions timeOptions,
00082                                            const KCalendarSystem *calendar,
00083                                            const KLocale *locale,
00084                                            KLocale::DigitSet digitSet,
00085                                            KLocale::DateTimeFormatStandard formatStandard) const
00086 {
00087     // If not valid input, don't waste our time
00088     if (!fromDateTime.isValid() || !calendar->isValid(fromDateTime.date()) || toFormat.isEmpty()) {
00089         return QString();
00090     }
00091 
00092     if (formatStandard == KLocale::UnicodeFormat) {
00093         return formatDateTimeUnicode(fromDateTime, toFormat, timeOptions, calendar, locale, digitSet);
00094     } else {
00095         return formatDateTimePosix(fromDateTime, toFormat, timeOptions, calendar, locale, digitSet, formatStandard);
00096     }
00097 }
00098 
00099 // Format an input date to match a POSIX date format string
00100 QString KDateTimeFormatter::formatDateTimePosix(const KDateTime &fromDateTime,
00101                                                 const QString &toFormat,
00102                                                 KLocale::TimeFormatOptions timeOptions,
00103                                                 const KCalendarSystem *calendar,
00104                                                 const KLocale *locale,
00105                                                 KLocale::DigitSet digitSet,
00106                                                 KLocale::DateTimeFormatStandard formatStandard) const
00107 {
00108 //kDebug() << "formatDateTimePosix(" << fromDateTime << toFormat << ")";
00109     // If not valid input, don't waste our time
00110     if (!fromDateTime.isValid() || toFormat.isEmpty()) {
00111         return QString();
00112     }
00113 
00114     QChar thisChar;  // Current toFormat char being processed
00115     QString result;  // Output string
00116 
00117     int padWidth = 0;     // The width to pad numbers to
00118     QChar padChar = QLatin1Char('0');  // The char to use when padding numbers
00119     QChar signChar;       // The sign to use when formatting numbers
00120     QChar caseChar;       // The case modifier to use
00121 
00122     bool escape = false;       // Are we processing an escape char (%)
00123     bool escapeWidth = false;  // Are we processing an escape width
00124     bool escapePad = false;    // Are we processing an escape pad char
00125     bool escapeMod = false;    // Are we processing an escape modifier
00126     int escapeIndex = 0;         // Position in string of current escape char (%)
00127 
00128     QChar modifierChar = QChar();
00129     bool invalidModifier = false;
00130 
00131     // Pre-fetch the core date components as they get used a lot
00132     // and it is 1/3rd more efficient than 3 separatre calls
00133     int year, month, day;
00134     calendar->getDate(fromDateTime.date(), &year, &month, &day);
00135 
00136     for (int formatIndex = 0; formatIndex < toFormat.length(); ++formatIndex) {
00137 
00138         thisChar = toFormat.at(formatIndex);
00139 
00140         if (!escape) {
00141 
00142             if (thisChar == QLatin1Char('%')) {
00143                 escape = true;
00144                 escapeIndex = formatIndex;
00145             } else {
00146                 result.append(toFormat.at(formatIndex));
00147             }
00148 
00149         } else if (!escapeMod && !escapeWidth && thisChar == QLatin1Char('-')) {   // no padding
00150 
00151             padChar = QChar();
00152             escapePad = true;
00153 
00154         } else if (!escapeMod && !escapeWidth && thisChar == QLatin1Char('_')) {   // space padding
00155 
00156             padChar = QLatin1Char(' ');
00157             escapePad = true;
00158 
00159         } else if (!escapeMod && !escapeWidth && thisChar == QLatin1Char('0')) {   // 0 padding
00160 
00161             padChar = QLatin1Char('0');
00162             escapePad = true;
00163 
00164         } else if (!escapeMod && !escapeWidth && (thisChar == QLatin1Char('^') || thisChar == QLatin1Char('#'))) {     // Change case
00165 
00166             caseChar = thisChar;
00167 
00168         } else if (!escapeMod &&
00169                    ((!escapeWidth && thisChar >= QLatin1Char('1') && thisChar <= QLatin1Char('9')) ||
00170                     (escapeWidth && thisChar >= QLatin1Char('0') && thisChar <= QLatin1Char('9')))) {     // Change width
00171 
00172             if (escapeWidth) {
00173                 padWidth = padWidth * 10;
00174             }
00175             padWidth = padWidth + QString(thisChar).toInt();
00176             escapeWidth = true;
00177 
00178         } else if (!escapeMod && (thisChar == QLatin1Char('E') || thisChar == QLatin1Char('O') || thisChar == QLatin1Char(':'))) {     // Set modifier
00179 
00180             escapeMod = true;
00181             modifierChar = thisChar;
00182             if (thisChar == QLatin1Char(':')) {
00183                 invalidModifier = true;
00184             }
00185 
00186         } else {
00187 
00188             bool invalidComponent = false;
00189             QString componentString;
00190             int componentInteger = 0;
00191             int minWidth = 0;
00192             int isoWeekYear = year;
00193             QDate yearDate;
00194             KDateTime::SpecType timeSpecType;
00195 
00196             //Default settings unless overridden by pad and case flags and width: are 0 pad to 0 width no sign
00197             //Names will override 0 pad with no pad unless flagged
00198             //Numbers will override with correct width unless flagged
00199             QChar thisChar = toFormat.at(formatIndex).unicode();
00200             switch (thisChar.unicode()) {
00201             case '%':  //Literal %
00202                 if (modifierChar != QLatin1Char(':')) {    // E and O mods are ignored if not used, but : is treated as literal
00203                     componentString = QLatin1Char('%');
00204                     if (!escapePad) {
00205                         padChar = QChar();
00206                     }
00207                 }
00208                 break;
00209             case 't':  //Tab
00210                 if (modifierChar != QLatin1Char(':')) {
00211                     componentString = QString::fromLatin1("\t");
00212                     if (!escapePad) {
00213                         padChar = QChar();
00214                     }
00215                 }
00216                 break;
00217             case 'Y':
00218                 if (modifierChar == QLatin1Char('E')) {    //Era Year, default no pad to 0 places no sign
00219                     if (!escapePad) {
00220                         padChar = QLatin1Char(' ');
00221                     }
00222                     componentString = calendar->eraYear(fromDateTime.date());
00223                 } else if (modifierChar != QLatin1Char(':')) {    //Long year numeric, default 0 pad to 4 places with sign
00224                     componentInteger = qAbs(year);
00225                     minWidth = 4;
00226                     if (year < 0) {
00227                         signChar = QLatin1Char('-');
00228                     }
00229                 }
00230                 break;
00231             case 'C':
00232                 if (modifierChar == QLatin1Char('E')) {    //Era name, default no pad to 0 places no sign
00233                     if (!escapePad) {
00234                         padChar = QLatin1Char(' ');
00235                     }
00236                     componentString = calendar->eraName(fromDateTime.date());
00237                 } else if (modifierChar != QLatin1Char(':')) {    //Century numeric, default 0 pad to 2 places with sign
00238                     componentInteger =  qAbs(year) / 100 ;
00239                     minWidth = 2;
00240                     if (year < 0) {
00241                         signChar = QLatin1Char('-');
00242                     }
00243                 }
00244                 break;
00245             case 'y':
00246                 if (modifierChar == QLatin1Char('E')) {    //Year in Era number, default 0 pad to 1 places no sign
00247                     componentInteger =  calendar->yearInEra(fromDateTime.date());
00248                     minWidth = 1;
00249                 } else if (modifierChar != QLatin1Char(':')) {    //Short year numeric, default 0 pad to 2 places with sign
00250                     componentInteger =  qAbs(year) % 100;
00251                     minWidth = 2;
00252                     if (year < 0) {
00253                         signChar = QLatin1Char('-');
00254                     }
00255                 }
00256                 break;
00257             case 'm':  // Month numeric
00258                 componentInteger =  month;
00259                 if (modifierChar == QLatin1Char(':')) {    //Short month numeric, default no pad to 1 places no sign
00260                     minWidth = 1;
00261                     if (!escapePad) {
00262                         padChar = QChar();
00263                     }
00264                     invalidModifier = false;
00265                 } else {  //Long month numeric, default 0 pad to 2 places no sign
00266                     componentInteger =  month;
00267                     minWidth = 2;
00268                 }
00269                 break;
00270             case 'n':
00271                 //PosixFormat %n is newline
00272                 //KdeFormat %n is short month numeric
00273                 if (modifierChar != QLatin1Char(':')) {
00274                     if (formatStandard == KLocale::KdeFormat) {
00275                         //Copy what %e does, no padding by default
00276                         //Short month numeric, default no pad to 1 places no sign
00277                         componentInteger =  month;
00278                         minWidth = 1;
00279                         if (!escapePad) {
00280                             padChar = QChar();
00281                         }
00282                     } else {  // formatStandard == KLocale::PosixFormat
00283                         componentString = QLatin1Char('\n');
00284                     }
00285                 }
00286                 break;
00287             case 'd':  //Long day numeric, default 0 pad to 2 places no sign
00288                 if (modifierChar != QLatin1Char(':')) {
00289                     componentInteger =  day;
00290                     minWidth = 2;
00291                 }
00292                 break;
00293             case 'e':  //Short day numeric, default no sign
00294                 //PosixFormat %e is space pad to 2 places
00295                 //KdeFormat %e is no pad to 1 place
00296                 if (modifierChar != QLatin1Char(':')) {
00297                     componentInteger =  day;
00298                     if (formatStandard == KLocale::KdeFormat) {
00299                         minWidth = 1;
00300                         if (!escapePad) {
00301                             padChar = QChar();
00302                         }
00303                     } else {  // formatStandard == KLocale::PosixFormat
00304                         minWidth = 2;
00305                         if (!escapePad) {
00306                             padChar = QLatin1Char(' ');
00307                         }
00308                     }
00309                 }
00310                 break;
00311             case 'B':  //Long month name, default space pad to 0 places no sign
00312                 if (locale->dateMonthNamePossessive()) {
00313                     if (modifierChar == QLatin1Char(':')) {
00314                         invalidModifier = false;
00315                         initEnglish(calendar, locale);
00316                         componentString = m_englishCalendar->monthName(month, year, KCalendarSystem::LongNamePossessive);
00317                     } else {
00318                         componentString = calendar->monthName(month, year, KCalendarSystem::LongNamePossessive);
00319                     }
00320                 } else {
00321                     if (modifierChar == QLatin1Char(':')) {
00322                         invalidModifier = false;
00323                         initEnglish(calendar, locale);
00324                         componentString = m_englishCalendar->monthName(month, year, KCalendarSystem::LongName);
00325                     } else {
00326                         componentString = calendar->monthName(month, year, KCalendarSystem::LongName);
00327                     }
00328                 }
00329                 if (!escapePad) {
00330                     padChar = QLatin1Char(' ');
00331                 }
00332                 break;
00333             case 'h':  //Short month name, default space pad to 0 places no sign
00334             case 'b':  //Short month name, default space pad to 0 places no sign
00335                 if (locale->dateMonthNamePossessive()) {
00336                     if (modifierChar == QLatin1Char(':')) {
00337                         invalidModifier = false;
00338                         initEnglish(calendar, locale);
00339                         componentString = m_englishCalendar->monthName(month, year, KCalendarSystem::ShortNamePossessive);
00340                     } else {
00341                         componentString = calendar->monthName(month, year, KCalendarSystem::ShortNamePossessive);
00342                     }
00343                 } else {
00344                     if (modifierChar == QLatin1Char(':')) {
00345                         invalidModifier = false;
00346                         initEnglish(calendar, locale);
00347                         componentString = m_englishCalendar->monthName(month, year, KCalendarSystem::ShortName);
00348                     } else {
00349                         componentString = calendar->monthName(month, year, KCalendarSystem::ShortName);
00350                     }
00351                 }
00352                 if (!escapePad) {
00353                     padChar = QLatin1Char(' ');
00354                 }
00355                 break;
00356             case 'A':  //Long weekday name, default space pad to 0 places no sign
00357                 if (modifierChar == QLatin1Char(':')) {
00358                     invalidModifier = false;
00359                     initEnglish(calendar, locale);
00360                     componentString = m_englishCalendar->weekDayName(fromDateTime.date(), KCalendarSystem::LongDayName);
00361                 } else {
00362                     componentString = calendar->weekDayName(fromDateTime.date(), KCalendarSystem::LongDayName);
00363                 }
00364                 if (!escapePad) {
00365                     padChar = QLatin1Char(' ');
00366                 }
00367                 break;
00368             case 'a':  //Short weekday name, default space pad to 0 places no sign
00369                 if (modifierChar == QLatin1Char(':')) {
00370                     invalidModifier = false;
00371                     initEnglish(calendar, locale);
00372                     componentString = m_englishCalendar->weekDayName(fromDateTime.date(), KCalendarSystem::ShortDayName);
00373                 } else {
00374                     componentString = calendar->weekDayName(fromDateTime.date(), KCalendarSystem::ShortDayName);
00375                 }
00376                 if (!escapePad) {
00377                     padChar = QLatin1Char(' ');
00378                 }
00379                 break;
00380             case 'j':  //Long day of year numeric, default 0 pad to 3 places no sign
00381                 if (modifierChar != QLatin1Char(':')) {
00382                     componentInteger = calendar->dayOfYear(fromDateTime.date());
00383                     minWidth = 3;
00384                 }
00385                 break;
00386             case 'V':  //Long ISO week of year numeric, default 0 pad to 2 places no sign
00387                 if (modifierChar != QLatin1Char(':')) {
00388                     componentInteger = calendar->week(fromDateTime.date(), KLocale::IsoWeekNumber);
00389                     minWidth = 2;
00390                 }
00391                 break;
00392             case 'G':  //Long year of ISO week of year numeric, default 0 pad to 4 places with sign
00393                 if (modifierChar != QLatin1Char(':')) {
00394                     calendar->week(fromDateTime.date(), KLocale::IsoWeekNumber, &isoWeekYear);
00395                     calendar->setDate(yearDate, isoWeekYear, 1, 1);
00396                     componentInteger = qAbs(isoWeekYear);
00397                     minWidth = 4;
00398                     if (isoWeekYear < 0) {
00399                         signChar = QLatin1Char('-');
00400                     }
00401                 }
00402                 break;
00403             case 'g':  //Short year of ISO week of year numeric, default 0 pad to 2 places with sign
00404                 if (modifierChar != QLatin1Char(':')) {
00405                     calendar->week(fromDateTime.date(), KLocale::IsoWeekNumber, &isoWeekYear);
00406                     calendar->setDate(yearDate, isoWeekYear, 1, 1);
00407                     componentInteger = qAbs(isoWeekYear) % 100;
00408                     minWidth = 2;
00409                     if (isoWeekYear < 0) {
00410                         signChar = QLatin1Char('-');
00411                     }
00412                 }
00413                 break;
00414             case 'u':
00415                 if (modifierChar == QLatin1Char(':')) {    // TZ UTC offset hours
00416                     invalidModifier = false;
00417                     KDateTime::SpecType timeSpecType = fromDateTime.timeType();
00418                     if (timeSpecType == KDateTime::UTC || timeSpecType == KDateTime::TimeZone ||
00419                             timeSpecType == KDateTime::OffsetFromUTC) {
00420                         componentInteger = fromDateTime.utcOffset() / 3600;
00421                         if (componentInteger >= 0) {
00422                             signChar = QLatin1Char('+');
00423                         } else {
00424                             componentInteger = -componentInteger;
00425                             signChar = QLatin1Char('-');
00426                         }
00427                         minWidth = 2;
00428                     }
00429                 } else {  // Short day of week numeric
00430                     componentInteger = calendar->dayOfWeek(fromDateTime.date());
00431                     minWidth = 1;
00432                 }
00433                 break;
00434             case 'D':  // US short date format, ignore any overrides
00435                 if (modifierChar != QLatin1Char(':')) {
00436                     componentString = formatDateTimePosix(fromDateTime, QString::fromLatin1("%m/%d/%y"), timeOptions, calendar, locale, digitSet, formatStandard);
00437                     padWidth = 0;
00438                     padChar = QChar();
00439                     caseChar = QChar();
00440                 }
00441                 break;
00442             case 'F':  // Full or ISO short date format, ignore any overrides
00443                 if (modifierChar != QLatin1Char(':')) {
00444                     componentString = formatDateTimePosix(fromDateTime, QString::fromLatin1("%Y-%m-%d"), timeOptions, calendar, locale, digitSet, formatStandard);
00445                     padWidth = 0;
00446                     padChar = QChar();
00447                     caseChar = QChar();
00448                 }
00449                 break;
00450             case 'x':  // Locale short date format, ignore any overrides
00451                 if (modifierChar != QLatin1Char(':')) {
00452                     componentString = formatDateTimePosix(fromDateTime, locale->dateFormatShort(), timeOptions, calendar, locale, digitSet, formatStandard);
00453                     padWidth = 0;
00454                     padChar = QChar();
00455                     caseChar = QChar();
00456                 }
00457                 break;
00458             case 'H':  // Long 24 hour
00459             case 'k':  // Short 24 hour
00460                 if (modifierChar != QLatin1Char(':')) {
00461                     componentInteger =  fromDateTime.time().hour();
00462                     minWidth = 1;
00463                     if (!escapePad) {
00464                         padChar = QChar();
00465                     }
00466                 }
00467                 break;
00468             case 'I':  // Long 12 hour
00469             case 'l':  // Short 12 hour
00470                 if (modifierChar != QLatin1Char(':')) {
00471                     if ((timeOptions & KLocale::TimeDuration) == KLocale::TimeDuration) {
00472                         componentInteger =  fromDateTime.time().hour();
00473                     } else {
00474                         componentInteger = locale->d->dayPeriodForTime(fromDateTime.time()).hourInPeriod(fromDateTime.time());
00475                     }
00476                     if (thisChar == QLatin1Char('I')) {
00477                         minWidth = 2;
00478                     } else {
00479                         minWidth = 1;
00480                         if (!escapePad) {
00481                             padChar = QChar();
00482                         }
00483                     }
00484                 }
00485                 break;
00486             case 'M':   // Long minutes
00487                 if (modifierChar != QLatin1Char(':')) {
00488                     componentInteger = fromDateTime.time().minute();
00489                     minWidth = 2;
00490                 }
00491                 break;
00492             case 'S':   // Long seconds
00493                 invalidModifier = false;
00494                 if ((timeOptions & KLocale::TimeWithoutSeconds) == KLocale::TimeWithoutSeconds) {
00495                     //TODO strip the preceding/following punctuation
00496                 } else {
00497                     componentInteger = fromDateTime.time().second();
00498                     if (modifierChar == QLatin1Char(':')) {    // Only if not 00 seconds
00499                         if (componentInteger > 0 || fromDateTime.time().msec() > 0) {
00500                             result.append(QLatin1Char(':'));
00501                             minWidth = 2;
00502                         }
00503                     } else {
00504                         minWidth = 2;
00505                     }
00506                 }
00507                 break;
00508             case 's':
00509                 if (modifierChar == QLatin1Char(':')) {    // Milliseconds
00510                     invalidModifier = false;
00511                     componentInteger = fromDateTime.time().msec();
00512                     minWidth = 3;
00513                 } else {  // Whole seconds since Unix Epoch
00514                     KDateTime unixEpoch;
00515                     unixEpoch.setTime_t(0);
00516                     componentInteger = unixEpoch.secsTo(fromDateTime);
00517                 }
00518                 break;
00519             case 'p':   // AM/PM symbol
00520             case 'P':   // AM/PM symbol in lowercase
00521                 if ((timeOptions & KLocale::TimeWithoutAmPm) == KLocale::TimeWithoutAmPm) {
00522                     //TODO strip the preceding/following punctuation
00523                 } else {
00524                     if (modifierChar == QLatin1Char(':')) {
00525                         invalidModifier = false;
00526                         initEnglish(calendar, locale);
00527                         componentString = m_englishLocale->d->dayPeriodForTime(fromDateTime.time()).periodName(KLocale::ShortName);
00528                     } else {
00529                         componentString = locale->d->dayPeriodForTime(fromDateTime.time()).periodName(KLocale::ShortName);
00530                     }
00531                     if (thisChar == QLatin1Char('P')) {
00532                         componentString = componentString.toLower();
00533                     }
00534                 }
00535                 break;
00536             case 'z':  // TZ UTC Offset
00537                 invalidModifier = false;
00538                 timeSpecType = fromDateTime.timeType();
00539                 if (timeSpecType == KDateTime::UTC || timeSpecType == KDateTime::TimeZone ||
00540                         timeSpecType == KDateTime::OffsetFromUTC) {
00541                     if (modifierChar == QLatin1Char(':')) {    // TZ UTC offset hours & minutes with colon
00542                         int offsetInSeconds = fromDateTime.utcOffset();
00543                         if (offsetInSeconds >= 0) {
00544                             signChar = QLatin1Char('+');
00545                         } else {
00546                             offsetInSeconds = -offsetInSeconds;
00547                             signChar = QLatin1Char('-');
00548                         }
00549                         int offsetHours = offsetInSeconds / 3600;
00550                         int offsetMinutes = (offsetInSeconds / 60) % 60;
00551                         //int offsetSeconds = offsetInSeconds % 60;
00552                         QString hourComponent = stringFromInteger(offsetHours, 2, QLatin1Char('0'), signChar, digitSet, locale);
00553                         QString minuteComponent = stringFromInteger(offsetMinutes, 2, QLatin1Char('0'), QChar(), digitSet, locale);
00554                         componentString = hourComponent + QLatin1Char(':') + minuteComponent;
00555                         minWidth = 0;
00556                         padChar = QChar();
00557                         padWidth = 0;
00558                     } else {  // TZ UTC offset hours & minutes
00559                         componentInteger = fromDateTime.utcOffset() / 60;
00560                         if (componentInteger >= 0) {
00561                             signChar = QLatin1Char('+');
00562                         } else {
00563                             componentInteger = -componentInteger;
00564                             signChar = QLatin1Char('-');
00565                         }
00566                         minWidth = 4;
00567                     }
00568                 }
00569                 break;
00570             case 'Z':  // TZ Name
00571                 invalidModifier = false;
00572                 timeSpecType = fromDateTime.timeType();
00573                 if (timeSpecType == KDateTime::UTC || timeSpecType == KDateTime::TimeZone) {
00574                     KTimeZone tz = fromDateTime.timeZone();
00575                     if (tz.isValid()) {
00576                         if (modifierChar == QLatin1Char(':')) {    // TZ full name
00577                             componentString = QString::fromLatin1(tz.abbreviation(fromDateTime.toUtc().dateTime()));
00578                         } else {  // TZ abbreviated name
00579                             componentString = tz.name();
00580                         }
00581                     }
00582                 }
00583                 break;
00584             default:  //No valid format code, treat as literal
00585                 invalidComponent = true;
00586                 break;
00587             }
00588 
00589             if (invalidComponent || invalidModifier) {    // If escape sequence invalid treat as literal
00590                 componentString = toFormat.mid(escapeIndex, formatIndex);
00591             } else if (componentString.isEmpty()) {    //i.e. is a number component
00592                 padWidth = qMax(minWidth, padWidth);
00593                 componentString = stringFromInteger(componentInteger, padWidth, padChar, signChar, digitSet, locale);
00594             } else { //i.e. is a string component
00595                 if (padChar != QChar() && padWidth != 0) {
00596                     componentString = componentString.rightJustified(padWidth, padChar);
00597                 }
00598 
00599                 if (caseChar == QLatin1Char('^')) {
00600                     componentString = componentString.toUpper();
00601                 } else if (caseChar == QLatin1Char('#')) {
00602                     componentString = componentString.toUpper(); // JPL ???
00603                 }
00604             }
00605 
00606             result.append(componentString);
00607 
00608             escape = false;
00609             escapePad = false;
00610             padChar = QLatin1Char('0');
00611             escapeMod = false;
00612             invalidModifier = false;
00613             invalidComponent = false;
00614             modifierChar = QChar();
00615             caseChar = QChar();
00616             escapeWidth = false;
00617             padWidth = 0;
00618             signChar = QChar();
00619         }
00620     }
00621 //kDebug() << " return = " << result;
00622 //kDebug() << "";
00623     return result;
00624 }
00625 
00626 void KDateTimeFormatter::initEnglish(const KCalendarSystem *calendar, const KLocale *locale) const
00627 {
00628     if (!m_englishCalendar || m_englishCalendar->calendarSystem() != calendar->calendarSystem()) {
00629         // Set up an English locale and calendar for use with ':' modifier which forces English names
00630         if (!m_englishLocale) {
00631             m_englishLocale = new KLocale(*locale);
00632             m_englishLocale->setLanguage(QStringList() << QString::fromLatin1("en_US"));
00633         }
00634         delete m_englishCalendar;
00635         m_englishCalendar = KCalendarSystem::create(calendar->calendarSystem(), m_englishLocale);
00636     }
00637 }
00638 
00639 // Reimplement if special string handling required
00640 // Format an input date to match a UNICODE date format string
00641 // Original QDate::fmtDateTime() code taken from Qt 4.7 under LGPL, now heavily modifed
00642 // Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
00643 QString KDateTimeFormatter::formatDateTimeUnicode(const KDateTime &fromDateTime,
00644                                                   const QString &toFormat,
00645                                                   KLocale::TimeFormatOptions timeOptions,
00646                                                   const KCalendarSystem *calendar,
00647                                                   const KLocale *locale,
00648                                                   KLocale::DigitSet digitSet) const
00649 {
00650     const QLatin1Char quote('\'');
00651 
00652     QString result;
00653     QString format;
00654     QChar status(QLatin1Char('0'));
00655 
00656     for (int i = 0; i < toFormat.length(); ++i) {
00657         if (toFormat.at(i) == quote) {
00658             if (status == quote) {
00659                 if (i > 0 && toFormat.at(i - 1) == quote)
00660                     result += QLatin1Char('\'');
00661                 status = QLatin1Char('0');
00662             } else {
00663                 if (!format.isEmpty()) {
00664                     result += getUnicodeString(fromDateTime, format, timeOptions, calendar, locale, digitSet);
00665                     format.clear();
00666                 }
00667                 status = quote;
00668             }
00669         } else if (status == quote) {
00670             result += toFormat.at(i);
00671         } else if (toFormat.at(i) == status) {
00672             if (toFormat.at(i) == QLatin1Char('P') ||
00673                     toFormat.at(i) == QLatin1Char('p')) {
00674                 status = QLatin1Char('0');
00675             }
00676             format += toFormat.at(i);
00677         } else {
00678             result += getUnicodeString(fromDateTime, format, timeOptions, calendar, locale, digitSet);
00679             format.clear();
00680             if ((toFormat.at(i) == QLatin1Char('d')) ||
00681                     (toFormat.at(i) == QLatin1Char('M')) ||
00682                     (toFormat.at(i) == QLatin1Char('y'))) {
00683                 status = toFormat.at(i);
00684                 format += toFormat.at(i);
00685             } else {
00686                 result += toFormat.at(i);
00687                 status = QLatin1Char('0');
00688             }
00689         }
00690     }
00691 
00692     result += getUnicodeString(fromDateTime, format, timeOptions, calendar, locale, digitSet);
00693 
00694     return result;
00695 }
00696 
00697 // Original QDate::getFmtString() code taken from Qt 4.7 under LGPL, now heavily modifed
00698 // Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
00699 // Replaces tokens by their value. See QDateTime::toString() for a list of valid tokens
00700 QString KDateTimeFormatter::getUnicodeString(const KDateTime &fromDateTime,
00701                                              const QString &toFormat,
00702                                              KLocale::TimeFormatOptions timeOptions,
00703                                              const KCalendarSystem *calendar,
00704                                              const KLocale *locale,
00705                                              KLocale::DigitSet digitSet) const
00706 {
00707     if (toFormat.isEmpty()) {
00708         return QString();
00709     }
00710 
00711     QString result = toFormat;
00712     int removed = 0;
00713 
00714     if (toFormat.startsWith(QLatin1String("dddd"))) {
00715         result = calendar->weekDayName(fromDateTime.date(), KCalendarSystem::LongDayName);
00716         removed = 4;
00717     } else if (toFormat.startsWith(QLatin1String("ddd"))) {
00718         result = calendar->weekDayName(fromDateTime.date(), KCalendarSystem::ShortDayName);
00719         removed = 3;
00720     } else if (toFormat.startsWith(QLatin1String("dd"))) {
00721         result = QString::number(calendar->day(fromDateTime.date())).rightJustified(2, QLatin1Char('0'), true);
00722         removed = 2;
00723     } else if (toFormat.at(0) == QLatin1Char('d')) {
00724         result = QString::number(calendar->day(fromDateTime.date()));
00725         removed = 1;
00726     } else if (toFormat.startsWith(QLatin1String("MMMM"))) {
00727         result = calendar->monthName(calendar->month(fromDateTime.date()), calendar->year(fromDateTime.date()), KCalendarSystem::LongName);
00728         removed = 4;
00729     } else if (toFormat.startsWith(QLatin1String("MMM"))) {
00730         result = calendar->monthName(calendar->month(fromDateTime.date()), calendar->year(fromDateTime.date()), KCalendarSystem::ShortName);
00731         removed = 3;
00732     } else if (toFormat.startsWith(QLatin1String("MM"))) {
00733         result = QString::number(calendar->month(fromDateTime.date())).rightJustified(2, QLatin1Char('0'), true);
00734         removed = 2;
00735     } else if (toFormat.at(0) == QLatin1Char('M')) {
00736         result = QString::number(calendar->month(fromDateTime.date()));
00737         removed = 1;
00738     } else if (toFormat.startsWith(QLatin1String("yyyy"))) {
00739         const int year = calendar->year(fromDateTime.date());
00740         result = QString::number(qAbs(year)).rightJustified(4, QLatin1Char('0'));
00741         if (year > 0)
00742             removed = 4;
00743         else {
00744             result.prepend(QLatin1Char('-'));
00745             removed = 5;
00746         }
00747     } else if (toFormat.startsWith(QLatin1String("yy"))) {
00748         result = QString::number(calendar->year(fromDateTime.date())).right(2).rightJustified(2, QLatin1Char('0'));
00749         removed = 2;
00750     }
00751 
00752     if (removed == 0 || removed >= toFormat.size()) {
00753         return result;
00754     }
00755 
00756     return result + getUnicodeString(fromDateTime, toFormat.mid(removed), timeOptions, calendar, locale, digitSet);
00757 }
00758 
00759 // Reimplement if special integer to string handling required, e.g. Hebrew.
00760 // Utility to convert an integer into the correct display string form
00761 QString KDateTimeFormatter::stringFromInteger(int number, int padWidth, QChar padChar, QChar signChar,
00762                                               KLocale::DigitSet digitSet, const KLocale *locale) const
00763 {
00764     if (padChar == QChar() && signChar == QChar()) {
00765 //kDebug() << "  stringFromInteger(" << number << padWidth << "null" << "null" << ")";
00766     } else if (padChar == QChar()) {
00767 //kDebug() << "  stringFromInteger(" << number << padWidth << "null" << signChar << ")";
00768     } else if (signChar == QChar()) {
00769 //kDebug() << "  stringFromInteger(" << number << padWidth << padChar << "null" << ")";
00770     } else if (signChar == QChar()) {
00771 //kDebug() << "  stringFromInteger(" << number << padWidth << padChar << signChar << ")";
00772     }
00773     QString result;
00774     if (padChar == QChar() || padWidth == 0) {   // If null pad char or 0 width don't bother padding
00775 //kDebug() << "    no pad";
00776         if (signChar == QChar()) {
00777             result = locale->convertDigits(QString::number(number), digitSet);
00778         } else {
00779             result = locale->convertDigits(QString::number(number).prepend(signChar), digitSet);
00780         }
00781     } else if (signChar != QChar()) {    // If sign required
00782         if (padChar == QLatin1Char('0')) {   // If zero-padded, zero considered part of the number, so pad the number then prepend the sign
00783 //kDebug() << "    zero pad with sign";
00784             result = locale->convertDigits(QString::number(number).rightJustified(padWidth, padChar).prepend(signChar), digitSet);
00785         } else { // If space-padded space not considered part of the number, so prepend the sign and then pad the number
00786 //kDebug() << "    space pad with sign";
00787             result = locale->convertDigits(QString::number(number).prepend(signChar).rightJustified(padWidth, padChar), digitSet);
00788         }
00789     } else {  // No sign required so just pad
00790 //kDebug() << "    pad no sign";
00791         result = locale->convertDigits(QString::number(number).rightJustified(padWidth, padChar), digitSet);
00792     }
00793 //kDebug() << "    result = " << result;
00794     return result;
00795 }

KDECore

Skip menu "KDECore"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.5
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal