KDELibs4Support

kdatetimeformatter.cpp
1 /*
2  Copyright 2009-2010 John Layt <[email protected]>
3  Copyright 2005-2010 David Jarvie <[email protected]>
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Library General Public License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to
17  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
19 */
20 
21 #include "kdatetimeformatter_p.h"
22 
23 #include <QDebug>
24 #include <QDate>
25 #include <QString>
26 #include <QStringList>
27 #include <QChar>
28 
29 #include "kdatetime.h"
30 #include "ktimezone.h"
31 #include "kcalendarsystem.h"
32 #include "kdayperiod_p.h"
33 #include "klocale_p.h"
34 
35 KDateTimeFormatter::KDateTimeFormatter()
36  : m_englishLocale(nullptr),
37  m_englishCalendar(nullptr)
38 {
39 }
40 
41 KDateTimeFormatter::~KDateTimeFormatter()
42 {
43  delete m_englishCalendar;
44  delete m_englishLocale;
45 }
46 
47 QString KDateTimeFormatter::formatDate(const QDate &fromDate,
48  const QString &toFormat,
49  const KCalendarSystem *calendar,
50  const KLocale *locale,
51  KLocale::DigitSet digitSet,
52  KLocale::DateTimeFormatStandard formatStandard) const
53 {
54  // If not valid input, don't waste our time
55  if (!calendar->isValid(fromDate) || toFormat.isEmpty()) {
56  return QString();
57  }
58 
59  return formatDateTime(KDateTime(fromDate), toFormat, nullptr, calendar, locale, digitSet, formatStandard);
60 }
61 
62 QString KDateTimeFormatter::formatTime(const QTime &fromTime,
63  const QString &toFormat,
64  KLocale::TimeFormatOptions timeOptions,
65  const KCalendarSystem *calendar,
66  const KLocale *locale,
67  KLocale::DigitSet digitSet,
68  KLocale::DateTimeFormatStandard formatStandard) const
69 {
70  // If not valid input, don't waste our time
71  if (fromTime.isValid() || toFormat.isEmpty()) {
72  return QString();
73  }
74 
75  return formatDateTime(KDateTime(QDate::currentDate(), fromTime), toFormat, timeOptions, calendar, locale, digitSet, formatStandard);
76 }
77 
78 // Format an input date to match a POSIX date format string
79 QString KDateTimeFormatter::formatDateTime(const KDateTime &fromDateTime,
80  const QString &toFormat,
81  KLocale::TimeFormatOptions timeOptions,
82  const KCalendarSystem *calendar,
83  const KLocale *locale,
84  KLocale::DigitSet digitSet,
85  KLocale::DateTimeFormatStandard formatStandard) const
86 {
87  // If not valid input, don't waste our time
88  if (!fromDateTime.isValid() || !calendar->isValid(fromDateTime.date()) || toFormat.isEmpty()) {
89  return QString();
90  }
91 
92  if (formatStandard == KLocale::UnicodeFormat) {
93  return formatDateTimeUnicode(fromDateTime, toFormat, timeOptions, calendar, locale, digitSet);
94  } else {
95  return formatDateTimePosix(fromDateTime, toFormat, timeOptions, calendar, locale, digitSet, formatStandard);
96  }
97 }
98 
99 // Format an input date to match a POSIX date format string
100 QString KDateTimeFormatter::formatDateTimePosix(const KDateTime &fromDateTime,
101  const QString &toFormat,
102  KLocale::TimeFormatOptions timeOptions,
103  const KCalendarSystem *calendar,
104  const KLocale *locale,
105  KLocale::DigitSet digitSet,
106  KLocale::DateTimeFormatStandard formatStandard) const
107 {
108 //qDebug() << "formatDateTimePosix(" << fromDateTime << toFormat << ")";
109  // If not valid input, don't waste our time
110  if (!fromDateTime.isValid() || toFormat.isEmpty()) {
111  return QString();
112  }
113 
114  QChar thisChar; // Current toFormat char being processed
115  QString result; // Output string
116 
117  int padWidth = 0; // The width to pad numbers to
118  QChar padChar = QLatin1Char('0'); // The char to use when padding numbers
119  QChar signChar; // The sign to use when formatting numbers
120  QChar caseChar; // The case modifier to use
121 
122  bool escape = false; // Are we processing an escape char (%)
123  bool escapeWidth = false; // Are we processing an escape width
124  bool escapePad = false; // Are we processing an escape pad char
125  bool escapeMod = false; // Are we processing an escape modifier
126  int escapeIndex = 0; // Position in string of current escape char (%)
127 
128  QChar modifierChar = QChar();
129  bool invalidModifier = false;
130 
131  // Pre-fetch the core date components as they get used a lot
132  // and it is 1/3rd more efficient than 3 separatre calls
133  int year, month, day;
134  calendar->getDate(fromDateTime.date(), &year, &month, &day);
135 
136  for (int formatIndex = 0; formatIndex < toFormat.length(); ++formatIndex) {
137 
138  thisChar = toFormat.at(formatIndex);
139 
140  if (!escape) {
141 
142  if (thisChar == QLatin1Char('%')) {
143  escape = true;
144  escapeIndex = formatIndex;
145  } else {
146  result.append(toFormat.at(formatIndex));
147  }
148 
149  } else if (!escapeMod && !escapeWidth && thisChar == QLatin1Char('-')) { // no padding
150 
151  padChar = QChar();
152  escapePad = true;
153 
154  } else if (!escapeMod && !escapeWidth && thisChar == QLatin1Char('_')) { // space padding
155 
156  padChar = QLatin1Char(' ');
157  escapePad = true;
158 
159  } else if (!escapeMod && !escapeWidth && thisChar == QLatin1Char('0')) { // 0 padding
160 
161  padChar = QLatin1Char('0');
162  escapePad = true;
163 
164  } else if (!escapeMod && !escapeWidth && (thisChar == QLatin1Char('^') || thisChar == QLatin1Char('#'))) { // Change case
165 
166  caseChar = thisChar;
167 
168  } else if (!escapeMod &&
169  ((!escapeWidth && thisChar >= QLatin1Char('1') && thisChar <= QLatin1Char('9')) ||
170  (escapeWidth && thisChar >= QLatin1Char('0') && thisChar <= QLatin1Char('9')))) { // Change width
171 
172  if (escapeWidth) {
173  padWidth = padWidth * 10;
174  }
175  padWidth = padWidth + QString(thisChar).toInt();
176  escapeWidth = true;
177 
178  } else if (!escapeMod && (thisChar == QLatin1Char('E') || thisChar == QLatin1Char('O') || thisChar == QLatin1Char(':'))) { // Set modifier
179 
180  escapeMod = true;
181  modifierChar = thisChar;
182  if (thisChar == QLatin1Char(':')) {
183  invalidModifier = true;
184  }
185 
186  } else {
187 
188  bool invalidComponent = false;
189  QString componentString;
190  int componentInteger = 0;
191  int minWidth = 0;
192  int isoWeekYear = year;
193  QDate yearDate;
194  KDateTime::SpecType timeSpecType;
195 
196  //Default settings unless overridden by pad and case flags and width: are 0 pad to 0 width no sign
197  //Names will override 0 pad with no pad unless flagged
198  //Numbers will override with correct width unless flagged
199  QChar thisChar = toFormat.at(formatIndex).unicode();
200  switch (thisChar.unicode()) {
201  case '%': //Literal %
202  if (modifierChar != QLatin1Char(':')) { // E and O mods are ignored if not used, but : is treated as literal
203  componentString = QLatin1Char('%');
204  if (!escapePad) {
205  padChar = QChar();
206  }
207  }
208  break;
209  case 't': //Tab
210  if (modifierChar != QLatin1Char(':')) {
211  componentString = QString::fromLatin1("\t");
212  if (!escapePad) {
213  padChar = QChar();
214  }
215  }
216  break;
217  case 'Y':
218  if (modifierChar == QLatin1Char('E')) { //Era Year, default no pad to 0 places no sign
219  if (!escapePad) {
220  padChar = QLatin1Char(' ');
221  }
222  componentString = calendar->eraYear(fromDateTime.date());
223  } else if (modifierChar != QLatin1Char(':')) { //Long year numeric, default 0 pad to 4 places with sign
224  componentInteger = qAbs(year);
225  minWidth = 4;
226  if (year < 0) {
227  signChar = QLatin1Char('-');
228  }
229  }
230  break;
231  case 'C':
232  if (modifierChar == QLatin1Char('E')) { //Era name, default no pad to 0 places no sign
233  if (!escapePad) {
234  padChar = QLatin1Char(' ');
235  }
236  componentString = calendar->eraName(fromDateTime.date());
237  } else if (modifierChar != QLatin1Char(':')) { //Century numeric, default 0 pad to 2 places with sign
238  componentInteger = qAbs(year) / 100;
239  minWidth = 2;
240  if (year < 0) {
241  signChar = QLatin1Char('-');
242  }
243  }
244  break;
245  case 'y':
246  if (modifierChar == QLatin1Char('E')) { //Year in Era number, default 0 pad to 1 places no sign
247  componentInteger = calendar->yearInEra(fromDateTime.date());
248  minWidth = 1;
249  } else if (modifierChar != QLatin1Char(':')) { //Short year numeric, default 0 pad to 2 places with sign
250  componentInteger = qAbs(year) % 100;
251  minWidth = 2;
252  if (year < 0) {
253  signChar = QLatin1Char('-');
254  }
255  }
256  break;
257  case 'm': // Month numeric
258  componentInteger = month;
259  if (modifierChar == QLatin1Char(':')) { //Short month numeric, default no pad to 1 places no sign
260  minWidth = 1;
261  if (!escapePad) {
262  padChar = QChar();
263  }
264  invalidModifier = false;
265  } else { //Long month numeric, default 0 pad to 2 places no sign
266  componentInteger = month;
267  minWidth = 2;
268  }
269  break;
270  case 'n':
271  //PosixFormat %n is newline
272  //KdeFormat %n is short month numeric
273  if (modifierChar != QLatin1Char(':')) {
274  if (formatStandard == KLocale::KdeFormat) {
275  //Copy what %e does, no padding by default
276  //Short month numeric, default no pad to 1 places no sign
277  componentInteger = month;
278  minWidth = 1;
279  if (!escapePad) {
280  padChar = QChar();
281  }
282  } else { // formatStandard == KLocale::PosixFormat
283  componentString = QLatin1Char('\n');
284  }
285  }
286  break;
287  case 'd': //Long day numeric, default 0 pad to 2 places no sign
288  if (modifierChar != QLatin1Char(':')) {
289  componentInteger = day;
290  minWidth = 2;
291  }
292  break;
293  case 'e': //Short day numeric, default no sign
294  //PosixFormat %e is space pad to 2 places
295  //KdeFormat %e is no pad to 1 place
296  if (modifierChar != QLatin1Char(':')) {
297  componentInteger = day;
298  if (formatStandard == KLocale::KdeFormat) {
299  minWidth = 1;
300  if (!escapePad) {
301  padChar = QChar();
302  }
303  } else { // formatStandard == KLocale::PosixFormat
304  minWidth = 2;
305  if (!escapePad) {
306  padChar = QLatin1Char(' ');
307  }
308  }
309  }
310  break;
311  case 'B': //Long month name, default space pad to 0 places no sign
312  if (locale->dateMonthNamePossessive()) {
313  if (modifierChar == QLatin1Char(':')) {
314  invalidModifier = false;
315  initEnglish(calendar, locale);
316  componentString = m_englishCalendar->monthName(month, year, KCalendarSystem::LongNamePossessive);
317  } else {
318  componentString = calendar->monthName(month, year, KCalendarSystem::LongNamePossessive);
319  }
320  } else {
321  if (modifierChar == QLatin1Char(':')) {
322  invalidModifier = false;
323  initEnglish(calendar, locale);
324  componentString = m_englishCalendar->monthName(month, year, KCalendarSystem::LongName);
325  } else {
326  componentString = calendar->monthName(month, year, KCalendarSystem::LongName);
327  }
328  }
329  if (!escapePad) {
330  padChar = QLatin1Char(' ');
331  }
332  break;
333  case 'h': //Short month name, default space pad to 0 places no sign
334  case 'b': //Short month name, default space pad to 0 places no sign
335  if (locale->dateMonthNamePossessive()) {
336  if (modifierChar == QLatin1Char(':')) {
337  invalidModifier = false;
338  initEnglish(calendar, locale);
339  componentString = m_englishCalendar->monthName(month, year, KCalendarSystem::ShortNamePossessive);
340  } else {
341  componentString = calendar->monthName(month, year, KCalendarSystem::ShortNamePossessive);
342  }
343  } else {
344  if (modifierChar == QLatin1Char(':')) {
345  invalidModifier = false;
346  initEnglish(calendar, locale);
347  componentString = m_englishCalendar->monthName(month, year, KCalendarSystem::ShortName);
348  } else {
349  componentString = calendar->monthName(month, year, KCalendarSystem::ShortName);
350  }
351  }
352  if (!escapePad) {
353  padChar = QLatin1Char(' ');
354  }
355  break;
356  case 'A': //Long weekday name, default space pad to 0 places no sign
357  if (modifierChar == QLatin1Char(':')) {
358  invalidModifier = false;
359  initEnglish(calendar, locale);
360  componentString = m_englishCalendar->weekDayName(fromDateTime.date(), KCalendarSystem::LongDayName);
361  } else {
362  componentString = calendar->weekDayName(fromDateTime.date(), KCalendarSystem::LongDayName);
363  }
364  if (!escapePad) {
365  padChar = QLatin1Char(' ');
366  }
367  break;
368  case 'a': //Short weekday name, default space pad to 0 places no sign
369  if (modifierChar == QLatin1Char(':')) {
370  invalidModifier = false;
371  initEnglish(calendar, locale);
372  componentString = m_englishCalendar->weekDayName(fromDateTime.date(), KCalendarSystem::ShortDayName);
373  } else {
374  componentString = calendar->weekDayName(fromDateTime.date(), KCalendarSystem::ShortDayName);
375  }
376  if (!escapePad) {
377  padChar = QLatin1Char(' ');
378  }
379  break;
380  case 'j': //Long day of year numeric, default 0 pad to 3 places no sign
381  if (modifierChar != QLatin1Char(':')) {
382  componentInteger = calendar->dayOfYear(fromDateTime.date());
383  minWidth = 3;
384  }
385  break;
386  case 'V': //Long ISO week of year numeric, default 0 pad to 2 places no sign
387  if (modifierChar != QLatin1Char(':')) {
388  componentInteger = calendar->week(fromDateTime.date(), KLocale::IsoWeekNumber);
389  minWidth = 2;
390  }
391  break;
392  case 'G': //Long year of ISO week of year numeric, default 0 pad to 4 places with sign
393  if (modifierChar != QLatin1Char(':')) {
394  calendar->week(fromDateTime.date(), KLocale::IsoWeekNumber, &isoWeekYear);
395  calendar->setDate(yearDate, isoWeekYear, 1, 1);
396  componentInteger = qAbs(isoWeekYear);
397  minWidth = 4;
398  if (isoWeekYear < 0) {
399  signChar = QLatin1Char('-');
400  }
401  }
402  break;
403  case 'g': //Short year of ISO week of year numeric, default 0 pad to 2 places with sign
404  if (modifierChar != QLatin1Char(':')) {
405  calendar->week(fromDateTime.date(), KLocale::IsoWeekNumber, &isoWeekYear);
406  calendar->setDate(yearDate, isoWeekYear, 1, 1);
407  componentInteger = qAbs(isoWeekYear) % 100;
408  minWidth = 2;
409  if (isoWeekYear < 0) {
410  signChar = QLatin1Char('-');
411  }
412  }
413  break;
414  case 'u':
415  if (modifierChar == QLatin1Char(':')) { // TZ UTC offset hours
416  invalidModifier = false;
417  KDateTime::SpecType timeSpecType = fromDateTime.timeType();
418  if (timeSpecType == KDateTime::UTC || timeSpecType == KDateTime::TimeZone ||
419  timeSpecType == KDateTime::OffsetFromUTC) {
420  componentInteger = fromDateTime.utcOffset() / 3600;
421  if (componentInteger >= 0) {
422  signChar = QLatin1Char('+');
423  } else {
424  componentInteger = -componentInteger;
425  signChar = QLatin1Char('-');
426  }
427  minWidth = 2;
428  }
429  } else { // Short day of week numeric
430  componentInteger = calendar->dayOfWeek(fromDateTime.date());
431  minWidth = 1;
432  }
433  break;
434  case 'D': // US short date format, ignore any overrides
435  if (modifierChar != QLatin1Char(':')) {
436  componentString = formatDateTimePosix(fromDateTime, QString::fromLatin1("%m/%d/%y"), timeOptions, calendar, locale, digitSet, formatStandard);
437  padWidth = 0;
438  padChar = QChar();
439  caseChar = QChar();
440  }
441  break;
442  case 'F': // Full or ISO short date format, ignore any overrides
443  if (modifierChar != QLatin1Char(':')) {
444  componentString = formatDateTimePosix(fromDateTime, QString::fromLatin1("%Y-%m-%d"), timeOptions, calendar, locale, digitSet, formatStandard);
445  padWidth = 0;
446  padChar = QChar();
447  caseChar = QChar();
448  }
449  break;
450  case 'x': // Locale short date format, ignore any overrides
451  if (modifierChar != QLatin1Char(':')) {
452  componentString = formatDateTimePosix(fromDateTime, locale->dateFormatShort(), timeOptions, calendar, locale, digitSet, formatStandard);
453  padWidth = 0;
454  padChar = QChar();
455  caseChar = QChar();
456  }
457  break;
458  case 'H': // Long 24 hour
459  case 'k': // Short 24 hour
460  if (modifierChar != QLatin1Char(':')) {
461  componentInteger = fromDateTime.time().hour();
462  minWidth = 1;
463  if (!escapePad) {
464  padChar = QChar();
465  }
466  }
467  break;
468  case 'I': // Long 12 hour
469  case 'l': // Short 12 hour
470  if (modifierChar != QLatin1Char(':')) {
471  if ((timeOptions & KLocale::TimeDuration) == KLocale::TimeDuration) {
472  componentInteger = fromDateTime.time().hour();
473  } else {
474  componentInteger = locale->d->dayPeriodForTime(fromDateTime.time()).hourInPeriod(fromDateTime.time());
475  }
476  if (thisChar == QLatin1Char('I')) {
477  minWidth = 2;
478  } else {
479  minWidth = 1;
480  if (!escapePad) {
481  padChar = QChar();
482  }
483  }
484  }
485  break;
486  case 'M': // Long minutes
487  if (modifierChar != QLatin1Char(':')) {
488  componentInteger = fromDateTime.time().minute();
489  minWidth = 2;
490  }
491  break;
492  case 'S': // Long seconds
493  invalidModifier = false;
494  if ((timeOptions & KLocale::TimeWithoutSeconds) == KLocale::TimeWithoutSeconds) {
495  //TODO strip the preceding/following punctuation
496  } else {
497  componentInteger = fromDateTime.time().second();
498  if (modifierChar == QLatin1Char(':')) { // Only if not 00 seconds
499  if (componentInteger > 0 || fromDateTime.time().msec() > 0) {
500  result.append(QLatin1Char(':'));
501  minWidth = 2;
502  }
503  } else {
504  minWidth = 2;
505  }
506  }
507  break;
508  case 's':
509  if (modifierChar == QLatin1Char(':')) { // Milliseconds
510  invalidModifier = false;
511  componentInteger = fromDateTime.time().msec();
512  minWidth = 3;
513  } else { // Whole seconds since Unix Epoch
514  KDateTime unixEpoch;
515  unixEpoch.setTime_t(0);
516  componentInteger = unixEpoch.secsTo(fromDateTime);
517  }
518  break;
519  case 'p': // AM/PM symbol
520  case 'P': // AM/PM symbol in lowercase
521  if ((timeOptions & KLocale::TimeWithoutAmPm) == KLocale::TimeWithoutAmPm) {
522  //TODO strip the preceding/following punctuation
523  } else {
524  if (modifierChar == QLatin1Char(':')) {
525  invalidModifier = false;
526  initEnglish(calendar, locale);
527  componentString = m_englishLocale->d->dayPeriodForTime(fromDateTime.time()).periodName(KLocale::ShortName);
528  } else {
529  componentString = locale->d->dayPeriodForTime(fromDateTime.time()).periodName(KLocale::ShortName);
530  }
531  if (thisChar == QLatin1Char('P')) {
532  componentString = componentString.toLower();
533  }
534  }
535  break;
536  case 'z': // TZ UTC Offset
537  invalidModifier = false;
538  timeSpecType = fromDateTime.timeType();
539  if (timeSpecType == KDateTime::UTC || timeSpecType == KDateTime::TimeZone ||
540  timeSpecType == KDateTime::OffsetFromUTC) {
541  if (modifierChar == QLatin1Char(':')) { // TZ UTC offset hours & minutes with colon
542  int offsetInSeconds = fromDateTime.utcOffset();
543  if (offsetInSeconds >= 0) {
544  signChar = QLatin1Char('+');
545  } else {
546  offsetInSeconds = -offsetInSeconds;
547  signChar = QLatin1Char('-');
548  }
549  int offsetHours = offsetInSeconds / 3600;
550  int offsetMinutes = (offsetInSeconds / 60) % 60;
551  //int offsetSeconds = offsetInSeconds % 60;
552  QString hourComponent = stringFromInteger(offsetHours, 2, QLatin1Char('0'), signChar, digitSet, locale);
553  QString minuteComponent = stringFromInteger(offsetMinutes, 2, QLatin1Char('0'), QChar(), digitSet, locale);
554  componentString = hourComponent + QLatin1Char(':') + minuteComponent;
555  minWidth = 0;
556  padChar = QChar();
557  padWidth = 0;
558  } else { // TZ UTC offset hours & minutes
559  componentInteger = fromDateTime.utcOffset() / 60;
560  if (componentInteger >= 0) {
561  signChar = QLatin1Char('+');
562  } else {
563  componentInteger = -componentInteger;
564  signChar = QLatin1Char('-');
565  }
566  minWidth = 4;
567  }
568  }
569  break;
570  case 'Z': // TZ Name
571  invalidModifier = false;
572  timeSpecType = fromDateTime.timeType();
573  if (timeSpecType == KDateTime::UTC || timeSpecType == KDateTime::TimeZone) {
574  KTimeZone tz = fromDateTime.timeZone();
575  if (tz.isValid()) {
576  if (modifierChar == QLatin1Char(':')) { // TZ full name
577  componentString = QString::fromLatin1(tz.abbreviation(fromDateTime.toUtc().dateTime()));
578  } else { // TZ abbreviated name
579  componentString = tz.name();
580  }
581  }
582  }
583  break;
584  default: //No valid format code, treat as literal
585  invalidComponent = true;
586  break;
587  }
588 
589  if (invalidComponent || invalidModifier) { // If escape sequence invalid treat as literal
590  componentString = toFormat.mid(escapeIndex, formatIndex);
591  } else if (componentString.isEmpty()) { //i.e. is a number component
592  padWidth = qMax(minWidth, padWidth);
593  componentString = stringFromInteger(componentInteger, padWidth, padChar, signChar, digitSet, locale);
594  } else { //i.e. is a string component
595  if (padChar != QChar() && padWidth != 0) {
596  componentString = componentString.rightJustified(padWidth, padChar);
597  }
598 
599  if (caseChar == QLatin1Char('^')) {
600  componentString = componentString.toUpper();
601  } else if (caseChar == QLatin1Char('#')) {
602  componentString = componentString.toUpper(); // JPL ???
603  }
604  }
605 
606  result.append(componentString);
607 
608  escape = false;
609  escapePad = false;
610  padChar = QLatin1Char('0');
611  escapeMod = false;
612  invalidModifier = false;
613  invalidComponent = false;
614  modifierChar = QChar();
615  caseChar = QChar();
616  escapeWidth = false;
617  padWidth = 0;
618  signChar = QChar();
619  }
620  }
621 //qDebug() << " return = " << result;
622 //qDebug() << "";
623  return result;
624 }
625 
626 void KDateTimeFormatter::initEnglish(const KCalendarSystem *calendar, const KLocale *locale) const
627 {
628  if (!m_englishCalendar || m_englishCalendar->calendarSystem() != calendar->calendarSystem()) {
629  // Set up an English locale and calendar for use with ':' modifier which forces English names
630  if (!m_englishLocale) {
631  m_englishLocale = new KLocale(*locale);
632  m_englishLocale->setLanguage(QStringList() << QString::fromLatin1("en_US"));
633  }
634  delete m_englishCalendar;
635  m_englishCalendar = KCalendarSystem::create(calendar->calendarSystem(), m_englishLocale);
636  }
637 }
638 
639 // Reimplement if special string handling required
640 // Format an input date to match a UNICODE date format string
641 // Original QDate::fmtDateTime() code taken from Qt 4.7 under LGPL, now heavily modifed
642 // Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
643 QString KDateTimeFormatter::formatDateTimeUnicode(const KDateTime &fromDateTime,
644  const QString &toFormat,
645  KLocale::TimeFormatOptions timeOptions,
646  const KCalendarSystem *calendar,
647  const KLocale *locale,
648  KLocale::DigitSet digitSet) const
649 {
650  const QLatin1Char quote('\'');
651 
652  QString result;
653  QString format;
654  QChar status(QLatin1Char('0'));
655 
656  for (int i = 0; i < toFormat.length(); ++i) {
657  if (toFormat.at(i) == quote) {
658  if (status == quote) {
659  if (i > 0 && toFormat.at(i - 1) == quote) {
660  result += QLatin1Char('\'');
661  }
662  status = QLatin1Char('0');
663  } else {
664  if (!format.isEmpty()) {
665  result += getUnicodeString(fromDateTime, format, timeOptions, calendar, locale, digitSet);
666  format.clear();
667  }
668  status = quote;
669  }
670  } else if (status == quote) {
671  result += toFormat.at(i);
672  } else if (toFormat.at(i) == status) {
673  if (toFormat.at(i) == QLatin1Char('P') ||
674  toFormat.at(i) == QLatin1Char('p')) {
675  status = QLatin1Char('0');
676  }
677  format += toFormat.at(i);
678  } else {
679  result += getUnicodeString(fromDateTime, format, timeOptions, calendar, locale, digitSet);
680  format.clear();
681  if ((toFormat.at(i) == QLatin1Char('d')) ||
682  (toFormat.at(i) == QLatin1Char('M')) ||
683  (toFormat.at(i) == QLatin1Char('y'))) {
684  status = toFormat.at(i);
685  format += toFormat.at(i);
686  } else {
687  result += toFormat.at(i);
688  status = QLatin1Char('0');
689  }
690  }
691  }
692 
693  result += getUnicodeString(fromDateTime, format, timeOptions, calendar, locale, digitSet);
694 
695  return result;
696 }
697 
698 // Original QDate::getFmtString() code taken from Qt 4.7 under LGPL, now heavily modifed
699 // Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
700 // Replaces tokens by their value. See QDateTime::toString() for a list of valid tokens
701 QString KDateTimeFormatter::getUnicodeString(const KDateTime &fromDateTime,
702  const QString &toFormat,
703  KLocale::TimeFormatOptions timeOptions,
704  const KCalendarSystem *calendar,
705  const KLocale *locale,
706  KLocale::DigitSet digitSet) const
707 {
708  if (toFormat.isEmpty()) {
709  return QString();
710  }
711 
712  QString result = toFormat;
713  int removed = 0;
714 
715  if (toFormat.startsWith(QLatin1String("dddd"))) {
716  result = calendar->weekDayName(fromDateTime.date(), KCalendarSystem::LongDayName);
717  removed = 4;
718  } else if (toFormat.startsWith(QLatin1String("ddd"))) {
719  result = calendar->weekDayName(fromDateTime.date(), KCalendarSystem::ShortDayName);
720  removed = 3;
721  } else if (toFormat.startsWith(QLatin1String("dd"))) {
722  result = QString::number(calendar->day(fromDateTime.date())).rightJustified(2, QLatin1Char('0'), true);
723  removed = 2;
724  } else if (toFormat.at(0) == QLatin1Char('d')) {
725  result = QString::number(calendar->day(fromDateTime.date()));
726  removed = 1;
727  } else if (toFormat.startsWith(QLatin1String("MMMM"))) {
728  result = calendar->monthName(calendar->month(fromDateTime.date()), calendar->year(fromDateTime.date()), KCalendarSystem::LongName);
729  removed = 4;
730  } else if (toFormat.startsWith(QLatin1String("MMM"))) {
731  result = calendar->monthName(calendar->month(fromDateTime.date()), calendar->year(fromDateTime.date()), KCalendarSystem::ShortName);
732  removed = 3;
733  } else if (toFormat.startsWith(QLatin1String("MM"))) {
734  result = QString::number(calendar->month(fromDateTime.date())).rightJustified(2, QLatin1Char('0'), true);
735  removed = 2;
736  } else if (toFormat.at(0) == QLatin1Char('M')) {
737  result = QString::number(calendar->month(fromDateTime.date()));
738  removed = 1;
739  } else if (toFormat.startsWith(QLatin1String("yyyy"))) {
740  const int year = calendar->year(fromDateTime.date());
741  result = QString::number(qAbs(year)).rightJustified(4, QLatin1Char('0'));
742  if (year > 0) {
743  removed = 4;
744  } else {
745  result.prepend(QLatin1Char('-'));
746  removed = 5;
747  }
748  } else if (toFormat.startsWith(QLatin1String("yy"))) {
749  const int year = calendar->year(fromDateTime.date());
750  result = QString::number(year).right(2).rightJustified(2, QLatin1Char('0'));
751  if (year > 0) {
752  removed = 2;
753  } else {
754  if (result.startsWith('0')) {
755  result = result.right(1);
756  }
757  result.prepend(QLatin1Char('-'));
758  removed = 3;
759  }
760  }
761 
762  if (removed == 0 || removed >= toFormat.size()) {
763  return result;
764  }
765 
766  return result + getUnicodeString(fromDateTime, toFormat.mid(removed), timeOptions, calendar, locale, digitSet);
767 }
768 
769 // Reimplement if special integer to string handling required, e.g. Hebrew.
770 // Utility to convert an integer into the correct display string form
771 QString KDateTimeFormatter::stringFromInteger(int number, int padWidth, QChar padChar, QChar signChar,
772  KLocale::DigitSet digitSet, const KLocale *locale) const
773 {
774  if (padChar == QChar() && signChar == QChar()) {
775 //qDebug() << " stringFromInteger(" << number << padWidth << "null" << "null" << ")";
776  } else if (padChar == QChar()) {
777 //qDebug() << " stringFromInteger(" << number << padWidth << "null" << signChar << ")";
778  } else if (signChar == QChar()) {
779 //qDebug() << " stringFromInteger(" << number << padWidth << padChar << "null" << ")";
780  } else if (signChar == QChar()) {
781 //qDebug() << " stringFromInteger(" << number << padWidth << padChar << signChar << ")";
782  }
783  QString result;
784  if (padChar == QChar() || padWidth == 0) { // If null pad char or 0 width don't bother padding
785 //qDebug() << " no pad";
786  if (signChar == QChar()) {
787  result = locale->convertDigits(QString::number(number), digitSet);
788  } else {
789  result = locale->convertDigits(QString::number(number).prepend(signChar), digitSet);
790  }
791  } else if (signChar != QChar()) { // If sign required
792  if (padChar == QLatin1Char('0')) { // If zero-padded, zero considered part of the number, so pad the number then prepend the sign
793 //qDebug() << " zero pad with sign";
794  result = locale->convertDigits(QString::number(number).rightJustified(padWidth, padChar).prepend(signChar), digitSet);
795  } else { // If space-padded space not considered part of the number, so prepend the sign and then pad the number
796 //qDebug() << " space pad with sign";
797  result = locale->convertDigits(QString::number(number).prepend(signChar).rightJustified(padWidth, padChar), digitSet);
798  }
799  } else { // No sign required so just pad
800 //qDebug() << " pad no sign";
801  result = locale->convertDigits(QString::number(number).rightJustified(padWidth, padChar), digitSet);
802  }
803 //qDebug() << " result = " << result;
804  return result;
805 }
NETWORKMANAGERQT_EXPORT NetworkManager::Status status()
Get the current networking status If the result is Unknown, the backend may be unconfigured or otherw...
Definition: networking.cpp:40
Long name possessive format, e.g.
int minute() const const
SpecType
The time specification type of a KDateTime instance.
Definition: kdatetime.h:158
QString eraName(const QDate &date, StringFormat format=ShortFormat) const
QString & append(QChar ch)
QString toUpper() const const
KDateTime()
Constructs an invalid date/time.
Definition: kdatetime.cpp:799
KTimeZone timeZone() const
Returns the time zone for the date/time.
Definition: kdatetime.cpp:923
bool isValid() const
Returns whether the date/time is valid.
Definition: kdatetime.cpp:864
QString escape(const QString &plain)
Date/times with associated time zone.
QString & prepend(QChar ch)
bool isValid() const
Checks whether the instance is valid.
Definition: ktimezone.cpp:638
int size() const const
bool isValid() const const
virtual int day(const QDate &date) const
Returns the day portion of a given date in the current calendar system.
virtual QString weekDayName(int weekDay, WeekDayNameFormat format=LongDayName) const =0
Gets specific calendar type week day name.
int second() const const
UNICODE Standard (Qt/Java/OSX/Windows)
Definition: klocale.h:697
Read/format time string as duration.
Definition: klocale.h:881
KCalendarSystem abstract base class, provides support for local Calendar Systems in KDE...
virtual KLocale::CalendarSystem calendarSystem() const =0
QString convertDigits(const QString &str, DigitSet digitSet, bool ignoreContext=false) const
Definition: klocale.cpp:135
void clear()
void setTime_t(qint64 seconds)
Sets the time to a UTC time, specified as seconds since 00:00:00 UTC 1st January 1970 (as returned by...
Definition: kdatetime.cpp:1103
QString dateFormatShort() const
Returns the currently selected short date format.
Definition: klocale.cpp:441
QString number(int n, int base)
int utcOffset() const
Returns the UTC offset associated with the date/time.
Definition: kdatetime.cpp:935
virtual int dayOfYear(const QDate &date) const
Returns the day number of year for the given date.
QString rightJustified(int width, QChar fill, bool truncate) const const
ISO Week Number.
Definition: klocale.h:683
qint64 secsTo(const KDateTime &other) const
Returns the number of seconds from this date/time to the other date/time.
Definition: kdatetime.cpp:1218
QByteArray abbreviation(const QDateTime &utcDateTime) const
Returns the time zone abbreviation current at a specified time.
Definition: ktimezone.cpp:676
int toInt(bool *ok, int base) const const
bool isEmpty() const const
KDateTime toUtc() const
Returns the time converted to UTC.
Definition: kdatetime.cpp:947
QDate date() const
Returns the date part of the date/time.
Definition: kdatetime.cpp:901
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
QDateTime dateTime() const
Returns the date/time component of the instance, ignoring the time zone.
Definition: kdatetime.cpp:909
virtual int month(const QDate &date) const
Returns the month portion of a given date in the current calendar system.
Read/format time string without am/pm suffix but.
Definition: klocale.h:877
int week(const QDate &date, int *yearNum) const
Returns the localized Week Number for the date.
Time zone functions.
Short name possessive format, e.g.
KDE Standard.
Definition: klocale.h:695
QString right(int n) const const
ushort unicode() const const
int hour() const const
QString toLower() const const
int msec() const const
A class representing a date and time with an associated time zone.
Definition: kdatetime.h:148
QString eraYear(const QDate &date, StringFormat format=ShortFormat) const
bool isValid(int year, int month, int day) const
Returns whether a given date is valid in this calendar system.
Base class representing a time zone.
Definition: ktimezone.h:415
Short text format, e.g.
Definition: klocale.h:776
virtual int year(const QDate &date) const
Returns the year portion of a given date in the current calendar system.
bool dateMonthNamePossessive() const
Use this to determine whether in dates a possessive form of month name is preferred ("of January" rat...
Definition: klocale.cpp:145
static KCalendarSystem * create(KLocale::CalendarSystem calendarSystem, const KLocale *locale)
a local time which has a fixed offset from UTC.
Definition: kdatetime.h:161
int yearInEra(const QDate &date) const
Short name format, e.g.
QString mid(int position, int n) const const
virtual QString monthName(int month, int year, MonthNameFormat format=LongName) const =0
Gets specific calendar type month name for a given month number If an invalid month is specified...
a UTC time.
Definition: kdatetime.h:160
KLocale provides support for language and country specific stuff.
Definition: klocale.h:75
DateTimeFormatStandard
Definition: klocale.h:694
QDate currentDate()
const QChar at(int position) const const
int length() const const
Short name format, e.g.
QString fromLatin1(const char *str, int size)
QString name() const
Returns the name of the time zone.
Definition: ktimezone.cpp:663
DigitSet
Definition: klocale.h:176
Long name format, e.g.
void getDate(const QDate date, int *year, int *month, int *day) const
virtual bool setDate(QDate &date, int year, int month, int day) const
Changes the date&#39;s year, month and day.
SpecType timeType() const
Returns the time specification type of the date/time, i.e.
Definition: kdatetime.cpp:918
Long name format, e.g.
QTime time() const
Returns the time part of the date/time.
Definition: kdatetime.cpp:905
int dayOfWeek(const QDate &date) const
Returns the weekday number for the given date.
a time in a specified time zone.
Definition: kdatetime.h:162
Exclude the seconds part of the time from display.
Definition: klocale.h:876
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Aug 10 2020 23:02:29 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.