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

KDECore

  • sources
  • kde-4.12
  • 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  QString str = inputString.simplified().toLower();
331  QString fmt = formatString.simplified();
332  int dd = -1;
333  int mm = -1;
334  int yy = 0;
335  bool parsedYear = false;
336  int ey = -1;
337  QString ee;
338  int dayInYear = -1;
339  int isoWeekNumber = -1;
340  int dayOfIsoWeek = -1;
341  int strpos = 0;
342  int fmtpos = 0;
343  //int readLength; // Temporary variable used when reading input
344  bool error = false;
345 
346  DateTimeComponents result;
347  result.error = error;
348  result.inputPosition = strpos;
349  result.formatPosition = fmtpos;
350  if (error) {
351  result.day = -1;
352  result.month = -1;
353  result.year = 0;
354  result.parsedYear = false;
355  result.eraName.clear();
356  result.yearInEra = -1;
357  result.dayInYear = -1;
358  result.isoWeekNumber = -1;
359  result.dayOfIsoWeek = -1;
360  } else {
361  result.day = dd;
362  result.month = mm;
363  result.year = yy;
364  result.parsedYear = parsedYear;
365  result.eraName = ee;
366  result.yearInEra = ey;
367  result.dayInYear = dayInYear;
368  result.isoWeekNumber = isoWeekNumber;
369  result.dayOfIsoWeek = dayOfIsoWeek;
370  }
371  return result;
372 }
373 
374 // Peel a number off the front of a string which may have other trailing chars after the number
375 // Stop either at either maxLength, eos, or first non-digit char
376 int KDateTimeParser::integerFromString(const QString &string, int maxLength, int &readLength) const
377 {
378  int value = -1;
379  int position = 0;
380  readLength = 0;
381  bool ok = false;
382 
383  if (maxLength < 0) {
384  maxLength = string.length();
385  }
386 
387  while (position < string.length() &&
388  position < maxLength &&
389  string.at(position).isDigit()) {
390  position++;
391  }
392 
393  if (position > 0) {
394  value = string.left(position).toInt(&ok);
395  if (ok) {
396  readLength = position;
397  } else {
398  value = -1;
399  }
400  }
401 
402  return value;
403 }
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
DateTimeComponents::dayOfIsoWeek
int dayOfIsoWeek
Definition: kdatetimeparser_p.h:43
kcalendarsystem.h
DateTimeComponents::inputPosition
int inputPosition
Definition: kdatetimeparser_p.h:44
QString
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
DateTimeComponents::day
int day
Definition: kdatetimeparser_p.h:35
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
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
DateTimeComponents::yearInEra
int yearInEra
Definition: kdatetimeparser_p.h:40
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:169
DateTimeComponents::parsedYear
bool parsedYear
Definition: kdatetimeparser_p.h:38
KCalendarSystem::ShortDayName
Short name format, e.g.
Definition: kcalendarsystem.h:67
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
DateTimeComponents::eraName
QString eraName
Definition: kdatetimeparser_p.h:39
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-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:47:08 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
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • 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