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

KDECore

  • sources
  • kde-4.14
  • kdelibs
  • kdecore
  • date
kdatetimeparser.cpp
Go to the documentation of this file.
1 /*
2  Copyright 2009, 2010 John Layt <john@layt.net>
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License as published by the Free Software Foundation; either
7  version 2 of the License, or (at your option) any later version.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Library General Public License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to
16  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  Boston, MA 02110-1301, USA.
18 */
19 
20 #include "kdatetimeparser_p.h"
21 
22 #include "kcalendarsystemprivate_p.h"
23 #include "kcalendarsystem.h"
24 #include "kcalendarera_p.h"
25 
26 #include "kdebug.h"
27 
28 KDateTimeParser::KDateTimeParser()
29 {
30 }
31 
32 KDateTimeParser::~KDateTimeParser()
33 {
34 }
35 
36 // Parse a DateTime input string and return just the Date component
37 QDate KDateTimeParser::parseDate(const QString &inputString,
38  const QString &formatString,
39  const KCalendarSystem *calendar,
40  const KLocale *locale,
41  KLocale::DigitSet digitSet,
42  KLocale::DateTimeFormatStandard formatStandard) const
43 {
44  DateTimeComponents result;
45  if (formatStandard == KLocale::UnicodeFormat) {
46  result = parseDateUnicode(inputString, formatString, calendar, locale, digitSet);
47  } else {
48  result = parseDatePosix(inputString, formatString, calendar, locale, digitSet, formatStandard);
49  }
50 
51  QDate resultDate;
52 
53  if (!result.error &&
54  formatString.simplified().length() <= result.formatPosition &&
55  inputString.simplified().length() <= result.inputPosition) {
56 
57  // If there were no parsing errors, and we have reached the end of both the input and
58  // format strings, then see if we have a valid date based on the components parsed
59 
60  // If we haven't parsed a year component, then assume this year
61  if (!result.parsedYear) {
62  result.year = calendar->year(QDate::currentDate());
63  }
64 
65  if ((!result.eraName.isEmpty() || result.yearInEra > -1) && result.month > 0 && result.day > 0) {
66  // Have parsed Era components as well as month and day components
67  calendar->setDate(resultDate, result.eraName, result.yearInEra, result.month, result.day);
68  } else if (result.month > 0 && result.day > 0) {
69  // Have parsed month and day components
70  calendar->setDate(resultDate, result.year, result.month, result.day);
71  } else if (result.dayInYear > 0) {
72  // Have parsed Day In Year component
73  calendar->setDate(resultDate, result.year, result.dayInYear);
74  } else if (result.isoWeekNumber > 0 && result.dayOfIsoWeek > 0) {
75  // Have parsed ISO Week components
76  calendar->setDateIsoWeek(resultDate, result.year, result.isoWeekNumber, result.dayOfIsoWeek);
77  }
78 
79  }
80 
81  return resultDate;
82 }
83 
84 DateTimeComponents KDateTimeParser::parseDatePosix(const QString &inputString,
85  const QString &formatString,
86  const KCalendarSystem *calendar,
87  const KLocale *locale,
88  KLocale::DigitSet digitSet,
89  KLocale::DateTimeFormatStandard standard) const
90 {
91  QString str = inputString.simplified().toLower();
92  QString fmt = formatString.simplified();
93  int dd = -1;
94  int mm = -1;
95  int yy = 0;
96  bool parsedYear = false;
97  int ey = -1;
98  QString ee;
99  int dayInYear = -1;
100  int isoWeekNumber = -1;
101  int dayOfIsoWeek = -1;
102  int strpos = 0;
103  int fmtpos = 0;
104  int readLength; // Temporary variable used when reading input
105  bool error = false;
106 
107  while (fmt.length() > fmtpos && str.length() > strpos && !error) {
108 
109  QChar fmtChar = fmt.at(fmtpos++);
110 
111  if (fmtChar != QLatin1Char('%')) {
112 
113  if (fmtChar.isSpace() && str.at(strpos).isSpace()) {
114  strpos++;
115  } else if (fmtChar.toLower() == str.at(strpos)) {
116  strpos++;
117  } else {
118  error = true;
119  }
120 
121  } else {
122  int j;
123  QString shortName, longName;
124  QChar modifierChar;
125  // remove space at the beginning
126  if (str.length() > strpos && str.at(strpos).isSpace()) {
127  strpos++;
128  }
129 
130  fmtChar = fmt.at(fmtpos++);
131  if (fmtChar == QLatin1Char('E')) {
132  modifierChar = fmtChar;
133  fmtChar = fmt.at(fmtpos++);
134  }
135 
136  switch (fmtChar.unicode()) {
137  case 'a': // Weekday Name Short
138  case 'A': // Weekday Name Long
139  error = true;
140  j = 1;
141  while (error && j <= calendar->d_ptr->maxDaysInWeek()) {
142  shortName = calendar->weekDayName(j, KCalendarSystem::ShortDayName).toLower();
143  longName = calendar->weekDayName(j, KCalendarSystem::LongDayName).toLower();
144  if (str.mid(strpos, longName.length()) == longName) {
145  strpos += longName.length();
146  error = false;
147  } else if (str.mid(strpos, shortName.length()) == shortName) {
148  strpos += shortName.length();
149  error = false;
150  }
151  ++j;
152  }
153  break;
154  case 'b': // Month Name Short
155  case 'h': // Month Name Short
156  case 'B': // Month Name Long
157  error = true;
158  j = 1;
159  while (error && j <= calendar->d_ptr->maxMonthsInYear()) {
160  // This may be a problem in calendar systems with variable number of months
161  // in the year and/or names of months that change depending on the year, e.g
162  // Hebrew. We really need to know the correct year first, but we may not have
163  // read it yet and will be using the current year instead
164  int monthYear;
165  if (parsedYear) {
166  monthYear = yy;
167  } else {
168  monthYear = calendar->year(QDate::currentDate());
169  }
170  if (calendar->locale()->dateMonthNamePossessive()) {
171  shortName = calendar->monthName(j, monthYear, KCalendarSystem::ShortNamePossessive).toLower();
172  longName = calendar->monthName(j, monthYear, KCalendarSystem::LongNamePossessive).toLower();
173  } else {
174  shortName = calendar->monthName(j, monthYear, KCalendarSystem::ShortName).toLower();
175  longName = calendar->monthName(j, monthYear, KCalendarSystem::LongName).toLower();
176  }
177  if (str.mid(strpos, longName.length()) == longName) {
178  mm = j;
179  strpos += longName.length();
180  error = false;
181  } else if (str.mid(strpos, shortName.length()) == shortName) {
182  mm = j;
183  strpos += shortName.length();
184  error = false;
185  }
186  ++j;
187  }
188  break;
189  case 'd': // Day Number Long
190  case 'e': // Day Number Short
191  dd = calendar->dayStringToInteger(str.mid(strpos), readLength);
192  strpos += readLength;
193  error = readLength <= 0;
194  break;
195  case 'n':
196  // PosixFormat %n is Newline
197  // KdeFormat %n is Month Number Short
198  if (standard == KLocale::KdeFormat) {
199  mm = calendar->monthStringToInteger(str.mid(strpos), readLength);
200  strpos += readLength;
201  error = readLength <= 0;
202  }
203  // standard == KLocale::PosixFormat
204  // all whitespace already 'eaten', no action required
205  break;
206  case 'm': // Month Number Long
207  mm = calendar->monthStringToInteger(str.mid(strpos), readLength);
208  strpos += readLength;
209  error = readLength <= 0;
210  break;
211  case 'Y': // Year Number Long
212  case 'y': // Year Number Short
213  if (modifierChar == QLatin1Char('E')) { // Year In Era
214  if (fmtChar == QLatin1Char('y')) {
215  ey = calendar->yearStringToInteger(str.mid(strpos), readLength);
216  strpos += readLength;
217  error = readLength <= 0;
218  } else {
219  error = true;
220  j = calendar->eraList()->count() - 1; // Start with the most recent
221  while (error && j >= 0) {
222  QString subFormat = calendar->eraList()->at(j).format();
223  QString subInput = str.mid(strpos);
224  DateTimeComponents subResult = parseDatePosix(subInput, subFormat, calendar, locale, digitSet, standard);
225  if (!subResult.error) {
226  if (subResult.parsedYear) {
227  yy = subResult.year;
228  parsedYear = true;
229  error = false;
230  strpos += subResult.inputPosition;
231  } else if (!subResult.eraName.isEmpty() && subResult.yearInEra >= 0) {
232  ee = subResult.eraName;
233  ey = subResult.yearInEra;
234  error = false;
235  strpos += subResult.inputPosition;
236  }
237  }
238  --j;
239  }
240  }
241  } else {
242  yy = calendar->yearStringToInteger(str.mid(strpos), readLength);
243  strpos += readLength;
244  if (fmtChar == QLatin1Char('y')) {
245  yy = calendar->applyShortYearWindow(yy);
246  }
247  error = readLength <= 0;
248  if (!error) {
249  parsedYear = true;
250  }
251  }
252  break;
253  case 'C': // Era
254  error = true;
255  if (modifierChar == QLatin1Char('E')) {
256  j = calendar->eraList()->count() - 1; // Start with the most recent
257  while (error && j >= 0) {
258  shortName = calendar->d_ptr->m_eraList->at(j).name(KLocale::ShortName).toLower();
259  longName = calendar->eraList()->at(j).name(KLocale::LongName).toLower();
260  if (str.mid(strpos, longName.length()) == longName) {
261  strpos += longName.length();
262  ee = longName;
263  error = false;
264  } else if (str.mid(strpos, shortName.length()) == shortName) {
265  strpos += shortName.length();
266  ee = shortName;
267  error = false;
268  }
269  --j;
270  }
271  }
272  break;
273  case 'j': // Day Of Year Number
274  dayInYear = integerFromString(str.mid(strpos), 3, readLength);
275  strpos += readLength;
276  error = readLength <= 0;
277  break;
278  case 'V': // ISO Week Number
279  isoWeekNumber = integerFromString(str.mid(strpos), 2, readLength);
280  strpos += readLength;
281  error = readLength <= 0;
282  break;
283  case 'u': // ISO Day Of Week
284  dayOfIsoWeek = integerFromString(str.mid(strpos), 1, readLength);
285  strpos += readLength;
286  error = readLength <= 0;
287  break;
288  }
289  }
290  }
291 
292  DateTimeComponents result;
293  result.error = error;
294  result.inputPosition = strpos;
295  result.formatPosition = fmtpos;
296  if (error) {
297  result.day = -1;
298  result.month = -1;
299  result.year = 0;
300  result.parsedYear = false;
301  result.eraName.clear();
302  result.yearInEra = -1;
303  result.dayInYear = -1;
304  result.isoWeekNumber = -1;
305  result.dayOfIsoWeek = -1;
306  } else {
307  result.day = dd;
308  result.month = mm;
309  result.year = yy;
310  result.parsedYear = parsedYear;
311  result.eraName = ee;
312  result.yearInEra = ey;
313  result.dayInYear = dayInYear;
314  result.isoWeekNumber = isoWeekNumber;
315  result.dayOfIsoWeek = dayOfIsoWeek;
316  }
317  return result;
318 }
319 
320 // Parse an input string to match a UNICODE DateTime format string and return any components found
321 DateTimeComponents KDateTimeParser::parseDateUnicode(const QString &inputString,
322  const QString &formatString,
323  const KCalendarSystem *calendar,
324  const KLocale *locale,
325  KLocale::DigitSet digitSet) const
326 {
327  Q_UNUSED(calendar);
328  Q_UNUSED(locale);
329  Q_UNUSED(digitSet);
330  Q_UNUSED(inputString);
331  Q_UNUSED(formatString);
332 
333  kWarning() << "KDateTimeParser::parseDateUnicode is not implemented";
334 
335  DateTimeComponents result;
336  result.error = true;
337  result.inputPosition = 0;
338  result.formatPosition = 0;
339  result.day = -1;
340  result.month = -1;
341  result.year = 0;
342  result.parsedYear = false;
343  result.eraName.clear();
344  result.yearInEra = -1;
345  result.dayInYear = -1;
346  result.isoWeekNumber = -1;
347  result.dayOfIsoWeek = -1;
348  return result;
349 }
350 
351 // Peel a number off the front of a string which may have other trailing chars after the number
352 // Stop either at either maxLength, eos, or first non-digit char
353 int KDateTimeParser::integerFromString(const QString &string, int maxLength, int &readLength) const
354 {
355  int value = -1;
356  int position = 0;
357  readLength = 0;
358  bool ok = false;
359 
360  if (maxLength < 0) {
361  maxLength = string.length();
362  }
363 
364  while (position < string.length() &&
365  position < maxLength &&
366  string.at(position).isDigit()) {
367  position++;
368  }
369 
370  if (position > 0) {
371  value = string.left(position).toInt(&ok);
372  if (ok) {
373  readLength = position;
374  } else {
375  value = -1;
376  }
377  }
378 
379  return value;
380 }
KCalendarSystemPrivate::m_eraList
QList< KCalendarEra > * m_eraList
Definition: kcalendarsystemprivate_p.h:107
kdatetimeparser_p.h
DateTimeComponents::formatPosition
int formatPosition
Definition: kdatetimeparser_p.h:45
KCalendarSystem::LongNamePossessive
Long name possessive format, e.g.
Definition: kcalendarsystem.h:59
KDateTimeParser::~KDateTimeParser
virtual ~KDateTimeParser()
Definition: kdatetimeparser.cpp:32
DateTimeComponents::isoWeekNumber
int isoWeekNumber
Definition: kdatetimeparser_p.h:42
KCalendarSystem::setDateIsoWeek
bool setDateIsoWeek(QDate &date, int year, int isoWeekNumber, int dayOfIsoWeek) const
Definition: kcalendarsystem.cpp:1272
DateTimeComponents::year
int year
Definition: kdatetimeparser_p.h:37
kdebug.h
KCalendarSystem::monthStringToInteger
virtual int monthStringToInteger(const QString &sNum, int &iLength) const
Definition: kcalendarsystem.cpp:2036
KCalendarSystem::monthName
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...
Definition: kcalendarsystem.cpp:1842
QChar
KCalendarEra::name
QString name(KLocale::DateTimeComponentFormat format=KLocale::DefaultComponentFormat) const
Definition: kcalendarera.cpp:55
QList::at
const T & at(int i) const
QString::simplified
QString simplified() const
DateTimeComponents::dayOfIsoWeek
int dayOfIsoWeek
Definition: kdatetimeparser_p.h:43
kcalendarsystem.h
DateTimeComponents::inputPosition
int inputPosition
Definition: kdatetimeparser_p.h:44
KCalendarSystem::applyShortYearWindow
int applyShortYearWindow(int inputYear) const
Definition: kcalendarsystem.cpp:2398
KLocale::UnicodeFormat
UNICODE Standard (Qt/Java/OSX/Windows)
Definition: klocale.h:832
KCalendarSystem
KCalendarSystem abstract base class, provides support for local Calendar Systems in KDE...
Definition: kcalendarsystem.h:40
DateTimeComponents::error
bool error
Definition: kdatetimeparser_p.h:46
QString::clear
void clear()
DateTimeComponents::day
int day
Definition: kdatetimeparser_p.h:35
QList::count
int count(const T &value) const
QChar::isSpace
bool isSpace() const
QString::isEmpty
bool isEmpty() const
kcalendarera_p.h
KDateTimeParser::parseDate
virtual QDate parseDate(const QString &dateString, const QString &format, const KCalendarSystem *calendar=KGlobal::locale() ->calendar(), const KLocale *locale=KGlobal::locale(), KLocale::DigitSet digitSet=KLocale::ArabicDigits, KLocale::DateTimeFormatStandard standard=KLocale::KdeFormat) const
Definition: kdatetimeparser.cpp:37
KLocale::LongName
Long text format, e.g.
Definition: klocale.h:915
QDate
QString
QChar::unicode
ushort unicode() const
kcalendarsystemprivate_p.h
KCalendarSystem::locale
const KLocale * locale() const
Returns the locale used for translations and formats for this calendar system instance.
Definition: kcalendarsystem.cpp:2479
KCalendarSystem::ShortNamePossessive
Short name possessive format, e.g.
Definition: kcalendarsystem.h:58
KLocale::KdeFormat
KDE Standard.
Definition: klocale.h:830
QString::toLower
QString toLower() const
DateTimeComponents::yearInEra
int yearInEra
Definition: kdatetimeparser_p.h:40
QLatin1Char
kWarning
#define kWarning
Definition: kdebug.h:322
QChar::toLower
QChar toLower() const
KCalendarSystem::yearStringToInteger
virtual int yearStringToInteger(const QString &sNum, int &iLength) const
Definition: kcalendarsystem.cpp:2018
KLocale::ShortName
Short text format, e.g.
Definition: klocale.h:914
KCalendarSystem::year
virtual int year(const QDate &date) const
Returns the year portion of a given date in the current calendar system.
Definition: kcalendarsystem.cpp:1331
KLocale::dateMonthNamePossessive
bool dateMonthNamePossessive() const
Use this to determine whether in dates a possessive form of month name is preferred ("of January" rat...
Definition: klocale.cpp:222
KGlobal::locale
KLocale * locale()
Returns the global locale object.
Definition: kglobal.cpp:170
DateTimeComponents::parsedYear
bool parsedYear
Definition: kdatetimeparser_p.h:38
KCalendarSystem::ShortDayName
Short name format, e.g.
Definition: kcalendarsystem.h:67
KCalendarEra::format
QString format() const
Definition: kcalendarera.cpp:64
QString::mid
QString mid(int position, int n) const
KLocale
KLocale provides support for country specific stuff like the national language.
Definition: klocale.h:69
KLocale::DateTimeFormatStandard
DateTimeFormatStandard
Definition: klocale.h:829
DateTimeComponents::dayInYear
int dayInYear
Definition: kdatetimeparser_p.h:41
QDate::currentDate
QDate currentDate()
QString::at
const QChar at(int position) const
DateTimeComponents::eraName
QString eraName
Definition: kdatetimeparser_p.h:39
QString::length
int length() const
KCalendarSystem::ShortName
Short name format, e.g.
Definition: kcalendarsystem.h:56
DateTimeComponents
Definition: kdatetimeparser_p.h:34
KCalendarSystem::dayStringToInteger
virtual int dayStringToInteger(const QString &sNum, int &iLength) const
Definition: kcalendarsystem.cpp:2042
KLocale::DigitSet
DigitSet
Definition: klocale.h:309
DateTimeComponents::month
int month
Definition: kdatetimeparser_p.h:36
KCalendarSystem::LongName
Long name format, e.g.
Definition: kcalendarsystem.h:57
KDateTimeParser::KDateTimeParser
KDateTimeParser()
Definition: kdatetimeparser.cpp:28
KCalendarSystem::setDate
virtual bool setDate(QDate &date, int year, int month, int day) const
Changes the date's year, month and day.
Definition: kcalendarsystem.cpp:1222
KCalendarSystem::LongDayName
Long name format, e.g.
Definition: kcalendarsystem.h:68
KCalendarSystem::weekDayName
virtual QString weekDayName(int weekDay, WeekDayNameFormat format=LongDayName) const =0
Gets specific calendar type week day name.
Definition: kcalendarsystem.cpp:1881
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:22:11 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDECore

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

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal