00001 #include <qregexp.h>
00002
00003 #include "kdebug.h"
00004
00005 #include "klocale.h"
00006
00007 QString i18n(const char *text)
00008 {
00009 return QString( text );
00010 }
00011
00012 QString i18n(const char *,const char *text)
00013 {
00014 return QString( text );
00015 }
00016
00017 inline void put_it_in( QChar *buffer, uint& index, const QString &s )
00018 {
00019 for ( uint l = 0; l < s.length(); l++ )
00020 buffer[index++] = s.at( l );
00021 }
00022
00023 inline void put_it_in( QChar *buffer, uint& index, int number )
00024 {
00025 buffer[index++] = number / 10 + '0';
00026 buffer[index++] = number % 10 + '0';
00027 }
00028
00029 static int readInt(const QString &str, uint &pos)
00030 {
00031 if (!str.at(pos).isDigit()) return -1;
00032 int result = 0;
00033 for (; str.length() > pos && str.at(pos).isDigit(); pos++)
00034 {
00035 result *= 10;
00036 result += str.at(pos).digitValue();
00037 }
00038
00039 return result;
00040 }
00041
00042 QString KLocale::formatTime(const QTime &pTime, bool includeSecs) const
00043 {
00044 const QString rst = timeFormat();
00045
00046
00047
00048 QChar *buffer = new QChar[rst.length() * 3 / 2 + 30];
00049
00050 uint index = 0;
00051 bool escape = false;
00052 int number = 0;
00053
00054 for ( uint format_index = 0; format_index < rst.length(); format_index++ )
00055 {
00056 if ( !escape )
00057 {
00058 if ( rst.at( format_index ).unicode() == '%' )
00059 escape = true;
00060 else
00061 buffer[index++] = rst.at( format_index );
00062 }
00063 else
00064 {
00065 switch ( rst.at( format_index ).unicode() )
00066 {
00067 case '%':
00068 buffer[index++] = '%';
00069 break;
00070 case 'H':
00071 put_it_in( buffer, index, pTime.hour() );
00072 break;
00073 case 'I':
00074 put_it_in( buffer, index, ( pTime.hour() + 11) % 12 + 1 );
00075 break;
00076 case 'M':
00077 put_it_in( buffer, index, pTime.minute() );
00078 break;
00079 case 'S':
00080 if (includeSecs)
00081 put_it_in( buffer, index, pTime.second() );
00082 else
00083 {
00084
00085
00086 --index;
00087 break;
00088 }
00089 break;
00090 case 'k':
00091 number = pTime.hour();
00092 case 'l':
00093
00094 if ( rst.at( format_index ).unicode() == 'l' )
00095 number = (pTime.hour() + 11) % 12 + 1;
00096 if ( number / 10 )
00097 buffer[index++] = number / 10 + '0';
00098 buffer[index++] = number % 10 + '0';
00099 break;
00100 case 'p':
00101 {
00102 QString s;
00103 if ( pTime.hour() >= 12 )
00104 put_it_in( buffer, index, i18n("pm") );
00105 else
00106 put_it_in( buffer, index, i18n("am") );
00107 break;
00108 }
00109 default:
00110 buffer[index++] = rst.at( format_index );
00111 break;
00112 }
00113 escape = false;
00114 }
00115 }
00116 QString ret( buffer, index );
00117 delete [] buffer;
00118 return ret;
00119 }
00120
00121 QString KLocale::formatDate(const QDate &pDate, bool shortFormat) const
00122 {
00123 const QString rst = shortFormat?dateFormatShort():dateFormat();
00124
00125
00126 QChar *buffer = new QChar[rst.length() * 3 / 2 + 50];
00127
00128 unsigned int index = 0;
00129 bool escape = false;
00130 int number = 0;
00131
00132 for ( uint format_index = 0; format_index < rst.length(); ++format_index )
00133 {
00134 if ( !escape )
00135 {
00136 if ( rst.at( format_index ).unicode() == '%' )
00137 escape = true;
00138 else
00139 buffer[index++] = rst.at( format_index );
00140 }
00141 else
00142 {
00143 switch ( rst.at( format_index ).unicode() )
00144 {
00145 case '%':
00146 buffer[index++] = '%';
00147 break;
00148 case 'Y':
00149 put_it_in( buffer, index, pDate.year() / 100 );
00150 case 'y':
00151 put_it_in( buffer, index, pDate.year() % 100 );
00152 break;
00153 case 'n':
00154 number = pDate.month();
00155 case 'e':
00156
00157 if ( rst.at( format_index ).unicode() == 'e' )
00158 number = pDate.day();
00159 if ( number / 10 )
00160 buffer[index++] = number / 10 + '0';
00161 buffer[index++] = number % 10 + '0';
00162 break;
00163 case 'm':
00164 put_it_in( buffer, index, pDate.month() );
00165 break;
00166 case 'b':
00167 put_it_in( buffer, index, monthName(pDate.month(), true) );
00168 break;
00169 case 'B':
00170 put_it_in( buffer, index, monthName(pDate.month(), false) );
00171 break;
00172 case 'd':
00173 put_it_in( buffer, index, pDate.day() );
00174 break;
00175 case 'a':
00176 put_it_in( buffer, index, weekDayName(pDate.dayOfWeek(), true) );
00177 break;
00178 case 'A':
00179 put_it_in( buffer, index, weekDayName(pDate.dayOfWeek(), false) );
00180 break;
00181 default:
00182 buffer[index++] = rst.at( format_index );
00183 break;
00184 }
00185 escape = false;
00186 }
00187 }
00188 QString ret( buffer, index );
00189 delete [] buffer;
00190 return ret;
00191 }
00192
00193 QString KLocale::formatDateTime(const QDateTime &pDateTime,
00194 bool shortFormat,
00195 bool includeSeconds) const
00196 {
00197 return i18n("concatenation of dates and time", "%1 %2")
00198 .arg( formatDate( pDateTime.date(), shortFormat ) )
00199 .arg( formatTime( pDateTime.time(), includeSeconds ) );
00200 }
00201
00202 QString KLocale::formatDateTime(const QDateTime &pDateTime) const
00203 {
00204 return formatDateTime(pDateTime, true);
00205 }
00206
00207 QDate KLocale::readDate(const QString &intstr, bool* ok) const
00208 {
00209 QDate date;
00210 date = readDate(intstr, true, ok);
00211 if (date.isValid()) return date;
00212 return readDate(intstr, false, ok);
00213 }
00214
00215 QDate KLocale::readDate(const QString &intstr, bool shortFormat, bool* ok) const
00216 {
00217 QString fmt = (shortFormat ? dateFormatShort() : dateFormat()).simplifyWhiteSpace();
00218 return readDate( intstr, fmt, ok );
00219 }
00220
00221 QDate KLocale::readDate(const QString &intstr, const QString &fmt, bool* ok) const
00222 {
00223
00224 QString str = intstr.simplifyWhiteSpace().lower();
00225 int day = -1, month = -1;
00226
00227 int year = QDate::currentDate().year();
00228 uint strpos = 0;
00229 uint fmtpos = 0;
00230
00231 while (fmt.length() > fmtpos || str.length() > strpos)
00232 {
00233 if ( !(fmt.length() > fmtpos && str.length() > strpos) )
00234 goto error;
00235
00236 QChar c = fmt.at(fmtpos++);
00237
00238 if (c != '%') {
00239 if (c.isSpace())
00240 strpos++;
00241 else if (c != str.at(strpos++))
00242 goto error;
00243 continue;
00244 }
00245
00246
00247 if (str.length() > strpos && str.at(strpos).isSpace())
00248 strpos++;
00249
00250 c = fmt.at(fmtpos++);
00251 switch (c)
00252 {
00253 case 'a':
00254 case 'A':
00255
00256 {
00257 for (int j = 1; j < 8; j++) {
00258 QString s = weekDayName(j, c == 'a').lower();
00259 int len = s.length();
00260 if (str.mid(strpos, len) == s)
00261 strpos += len;
00262 }
00263 break;
00264 }
00265 case 'b':
00266 case 'B':
00267 {
00268 for (int j = 1; j < 13; j++) {
00269 QString s = monthName(j, c == 'b').lower();
00270 int len = s.length();
00271 if (str.mid(strpos, len) == s) {
00272 month = j;
00273 strpos += len;
00274 }
00275 }
00276 break;
00277 }
00278 case 'd':
00279 case 'e':
00280 day = readInt(str, strpos);
00281 if (day < 1 || day > 31)
00282 goto error;
00283
00284 break;
00285
00286 case 'n':
00287 case 'm':
00288 month = readInt(str, strpos);
00289 if (month < 1 || month > 12)
00290 goto error;
00291
00292 break;
00293
00294 case 'Y':
00295 case 'y':
00296 year = readInt(str, strpos);
00297 if (year < 0)
00298 goto error;
00299
00300
00301 if (year < 69)
00302 year += 2000;
00303 else if (c == 'y')
00304 year += 1900;
00305
00306 break;
00307 }
00308 }
00309
00310 if ( year != -1 && month != -1 && day != -1 )
00311 {
00312 if (ok) *ok = true;
00313 return QDate(year, month, day);
00314 }
00315 error:
00316 if (ok) *ok = false;
00317 return QDate();
00318 }
00319
00320 QTime KLocale::readTime(const QString &intstr, bool *ok) const
00321 {
00322 QTime _time;
00323 _time = readTime(intstr, true, ok);
00324 if (_time.isValid()) return _time;
00325 return readTime(intstr, false, ok);
00326 }
00327
00328 QTime KLocale::readTime(const QString &intstr, bool seconds, bool *ok) const
00329 {
00330 QString str = intstr.simplifyWhiteSpace().lower();
00331 QString Format = timeFormat().simplifyWhiteSpace();
00332 if (!seconds)
00333 Format.replace(QRegExp(QString::fromLatin1(".%S")), QString::null);
00334
00335 int hour = -1, minute = -1, second = seconds ? -1 : 0;
00336 bool g_12h = false;
00337 bool pm = false;
00338 uint strpos = 0;
00339 uint Formatpos = 0;
00340
00341 while (Format.length() > Formatpos || str.length() > strpos)
00342 {
00343 if ( !(Format.length() > Formatpos && str.length() > strpos) ) goto error;
00344
00345 QChar c = Format.at(Formatpos++);
00346
00347 if (c != '%')
00348 {
00349 if (c.isSpace())
00350 strpos++;
00351 else if (c != str.at(strpos++))
00352 goto error;
00353 continue;
00354 }
00355
00356
00357 if (str.length() > strpos && str.at(strpos).isSpace())
00358 strpos++;
00359
00360 c = Format.at(Formatpos++);
00361 switch (c)
00362 {
00363 case 'p':
00364 {
00365 QString s;
00366 s = i18n("pm").lower();
00367 int len = s.length();
00368 if (str.mid(strpos, len) == s)
00369 {
00370 pm = true;
00371 strpos += len;
00372 }
00373 else
00374 {
00375 s = i18n("am").lower();
00376 len = s.length();
00377 if (str.mid(strpos, len) == s) {
00378 pm = false;
00379 strpos += len;
00380 }
00381 else
00382 goto error;
00383 }
00384 }
00385 break;
00386
00387 case 'k':
00388 case 'H':
00389 g_12h = false;
00390 hour = readInt(str, strpos);
00391 if (hour < 0 || hour > 23)
00392 goto error;
00393
00394 break;
00395
00396 case 'l':
00397 case 'I':
00398 g_12h = true;
00399 hour = readInt(str, strpos);
00400 if (hour < 1 || hour > 12)
00401 goto error;
00402
00403 break;
00404
00405 case 'M':
00406 minute = readInt(str, strpos);
00407 if (minute < 0 || minute > 59)
00408 goto error;
00409
00410 break;
00411
00412 case 'S':
00413 second = readInt(str, strpos);
00414 if (second < 0 || second > 59)
00415 goto error;
00416
00417 break;
00418 }
00419 }
00420 if (g_12h)
00421 {
00422 hour %= 12;
00423 if (pm) hour += 12;
00424 }
00425
00426 if (ok) *ok = true;
00427 return QTime(hour, minute, second);
00428
00429 error:
00430 if (ok) *ok = false;
00431 return QTime(-1, -1, -1);
00432
00433
00434 }
00435
00436 bool KLocale::use12Clock() const
00437 {
00438 return false;
00439 }
00440
00441 bool KLocale::weekStartsMonday() const
00442 {
00443 return true;
00444 }
00445
00446 QString KLocale::weekDayName(int i,bool shortName) const
00447 {
00448 if ( shortName )
00449 switch ( i )
00450 {
00451 case 1: return i18n("Monday", "Mon");
00452 case 2: return i18n("Tuesday", "Tue");
00453 case 3: return i18n("Wednesday", "Wed");
00454 case 4: return i18n("Thursday", "Thu");
00455 case 5: return i18n("Friday", "Fri");
00456 case 6: return i18n("Saturday", "Sat");
00457 case 7: return i18n("Sunday", "Sun");
00458 }
00459 else
00460 switch ( i )
00461 {
00462 case 1: return i18n("Monday");
00463 case 2: return i18n("Tuesday");
00464 case 3: return i18n("Wednesday");
00465 case 4: return i18n("Thursday");
00466 case 5: return i18n("Friday");
00467 case 6: return i18n("Saturday");
00468 case 7: return i18n("Sunday");
00469 }
00470
00471 return QString::null;
00472 }
00473
00474 QString KLocale::monthName(int i,bool shortName) const
00475 {
00476 if ( shortName )
00477 switch ( i )
00478 {
00479 case 1: return i18n("January", "Jan");
00480 case 2: return i18n("February", "Feb");
00481 case 3: return i18n("March", "Mar");
00482 case 4: return i18n("April", "Apr");
00483 case 5: return i18n("May short", "May");
00484 case 6: return i18n("June", "Jun");
00485 case 7: return i18n("July", "Jul");
00486 case 8: return i18n("August", "Aug");
00487 case 9: return i18n("September", "Sep");
00488 case 10: return i18n("October", "Oct");
00489 case 11: return i18n("November", "Nov");
00490 case 12: return i18n("December", "Dec");
00491 }
00492 else
00493 switch (i)
00494 {
00495 case 1: return i18n("January");
00496 case 2: return i18n("February");
00497 case 3: return i18n("March");
00498 case 4: return i18n("April");
00499 case 5: return i18n("May long", "May");
00500 case 6: return i18n("June");
00501 case 7: return i18n("July");
00502 case 8: return i18n("August");
00503 case 9: return i18n("September");
00504 case 10: return i18n("October");
00505 case 11: return i18n("November");
00506 case 12: return i18n("December");
00507 }
00508
00509 return QString::null;
00510 }
00511
00512 QString KLocale::country() const
00513 {
00514 return QString::null;
00515 }
00516
00517 QString KLocale::dateFormat() const
00518 {
00519 return "%A %d %B %Y";
00520 }
00521
00522 QString KLocale::dateFormatShort() const
00523 {
00524 return "%d.%m.%Y";
00525 }
00526
00527 QString KLocale::timeFormat() const
00528 {
00529 return "%H:%M:%S";
00530 }