• Skip to content
  • Skip to link menu
KDE 4.6 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->weekNumber( fromDateTime.date() );
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->weekNumber( fromDateTime.date(), &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->weekNumber( fromDateTime.date(), &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 preceeding/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 preceeding/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->calendarType() != calendar->calendarType() ) {
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->calendarType(), 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         {
00745             result.prepend( QLatin1Char('-') );
00746             removed = 5;
00747         }
00748     } else if ( toFormat.startsWith( QLatin1String("yy") ) ) {
00749         result = QString::number( calendar->year(fromDateTime.date()) ).right( 2 ).rightJustified( 2, QLatin1Char('0') );
00750         removed = 2;
00751     }
00752 
00753     if ( removed == 0 || removed >= toFormat.size() ) {
00754         return result;
00755     }
00756 
00757     return result + getUnicodeString( fromDateTime, toFormat.mid( removed ), timeOptions, calendar, locale, digitSet );
00758 }
00759 
00760 // Reimplement if special integer to string handling required, e.g. Hebrew.
00761 // Utility to convert an integer into the correct display string form
00762 QString KDateTimeFormatter::stringFromInteger( int number, int padWidth, QChar padChar, QChar signChar,
00763                                                KLocale::DigitSet digitSet, const KLocale *locale ) const
00764 {
00765 if ( padChar == QChar() && signChar == QChar() ) {
00766 //kDebug() << "  stringFromInteger(" << number << padWidth << "null" << "null" << ")";
00767 } else if ( padChar == QChar() ) {
00768 //kDebug() << "  stringFromInteger(" << number << padWidth << "null" << signChar << ")";
00769 } else if ( signChar == QChar() ) {
00770 //kDebug() << "  stringFromInteger(" << number << padWidth << padChar << "null" << ")";
00771 } else if ( signChar == QChar() ) {
00772 //kDebug() << "  stringFromInteger(" << number << padWidth << padChar << signChar << ")";
00773 }
00774     QString result;
00775     if ( padChar == QChar() || padWidth == 0 ) { // If null pad char or 0 width don't bother padding
00776 //kDebug() << "    no pad";
00777         if ( signChar == QChar() ) {
00778             result = locale->convertDigits( QString::number( number ), digitSet );
00779         } else {
00780             result = locale->convertDigits( QString::number( number ).prepend( signChar ), digitSet );
00781         }
00782     } else if ( signChar != QChar() ) {  // If sign required
00783         if ( padChar == QLatin1Char('0') ) { // If zero-padded, zero considered part of the number, so pad the number then prepend the sign
00784 //kDebug() << "    zero pad with sign";
00785             result = locale->convertDigits( QString::number( number ).rightJustified( padWidth, padChar ).prepend( signChar ), digitSet );
00786         } else { // If space-padded space not considered part of the number, so prepend the sign and then pad the number
00787 //kDebug() << "    space pad with sign";
00788             result = locale->convertDigits( QString::number( number ).prepend( signChar ).rightJustified( padWidth, padChar ), digitSet );
00789         }
00790     } else {  // No sign required so just pad
00791 //kDebug() << "    pad no sign";
00792         result = locale->convertDigits( QString::number( number ).rightJustified( padWidth, padChar ), digitSet );
00793     }
00794 //kDebug() << "    result = " << result;
00795     return result;
00796 }

KDECore

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • 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.3
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