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

KDECore

  • 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
28KDateTimeParser::KDateTimeParser()
29{
30}
31
32KDateTimeParser::~KDateTimeParser()
33{
34}
35
36// Parse a DateTime input string and return just the Date component
37QDate 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
84DateTimeComponents 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
321DateTimeComponents 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
353int 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
KCalendarSystem
KCalendarSystem abstract base class, provides support for local Calendar Systems in KDE.
Definition: kcalendarsystem.h:41
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
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
KCalendarSystem::monthStringToInteger
virtual int monthStringToInteger(const QString &sNum, int &iLength) const
Definition: kcalendarsystem.cpp:2036
KCalendarSystem::locale
const KLocale * locale() const
Returns the locale used for translations and formats for this calendar system instance.
Definition: kcalendarsystem.cpp:2479
KCalendarSystem::ShortName
@ ShortName
Short name format, e.g.
Definition: kcalendarsystem.h:56
KCalendarSystem::LongNamePossessive
@ LongNamePossessive
Long name possessive format, e.g.
Definition: kcalendarsystem.h:59
KCalendarSystem::ShortNamePossessive
@ ShortNamePossessive
Short name possessive format, e.g.
Definition: kcalendarsystem.h:58
KCalendarSystem::LongName
@ LongName
Long name format, e.g.
Definition: kcalendarsystem.h:57
KCalendarSystem::ShortDayName
@ ShortDayName
Short name format, e.g.
Definition: kcalendarsystem.h:67
KCalendarSystem::LongDayName
@ LongDayName
Long name format, e.g.
Definition: kcalendarsystem.h:68
KCalendarSystem::yearStringToInteger
virtual int yearStringToInteger(const QString &sNum, int &iLength) const
Definition: kcalendarsystem.cpp:2018
KCalendarSystem::dayStringToInteger
virtual int dayStringToInteger(const QString &sNum, int &iLength) const
Definition: kcalendarsystem.cpp:2042
KCalendarSystem::weekDayName
virtual QString weekDayName(int weekDay, WeekDayNameFormat format=LongDayName) const =0
Gets specific calendar type week day name.
Definition: kcalendarsystem.cpp:1881
KCalendarSystem::setDateIsoWeek
bool setDateIsoWeek(QDate &date, int year, int isoWeekNumber, int dayOfIsoWeek) const
Definition: kcalendarsystem.cpp:1272
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::applyShortYearWindow
int applyShortYearWindow(int inputYear) const
Definition: kcalendarsystem.cpp:2398
KDateTimeParser::~KDateTimeParser
virtual ~KDateTimeParser()
Definition: kdatetimeparser.cpp:32
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
KDateTimeParser::KDateTimeParser
KDateTimeParser()
Definition: kdatetimeparser.cpp:28
KLocale
KLocale provides support for country specific stuff like the national language.
Definition: klocale.h:70
KLocale::DigitSet
DigitSet
Definition: klocale.h:309
KLocale::DateTimeFormatStandard
DateTimeFormatStandard
Definition: klocale.h:829
KLocale::KdeFormat
@ KdeFormat
KDE Standard.
Definition: klocale.h:830
KLocale::UnicodeFormat
@ UnicodeFormat
UNICODE Standard (Qt/Java/OSX/Windows)
Definition: klocale.h:832
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
KLocale::LongName
@ LongName
Long text format, e.g.
Definition: klocale.h:915
KLocale::ShortName
@ ShortName
Short text format, e.g.
Definition: klocale.h:914
QString
kWarning
#define kWarning
Definition: kdebug.h:322
kcalendarera_p.h
kcalendarsystem.h
kcalendarsystemprivate_p.h
kdatetimeparser_p.h
kdebug.h
DateTimeComponents
Definition: kdatetimeparser_p.h:34
DateTimeComponents::month
int month
Definition: kdatetimeparser_p.h:36
DateTimeComponents::parsedYear
bool parsedYear
Definition: kdatetimeparser_p.h:38
DateTimeComponents::formatPosition
int formatPosition
Definition: kdatetimeparser_p.h:45
DateTimeComponents::error
bool error
Definition: kdatetimeparser_p.h:46
DateTimeComponents::day
int day
Definition: kdatetimeparser_p.h:35
DateTimeComponents::eraName
QString eraName
Definition: kdatetimeparser_p.h:39
DateTimeComponents::yearInEra
int yearInEra
Definition: kdatetimeparser_p.h:40
DateTimeComponents::year
int year
Definition: kdatetimeparser_p.h:37
DateTimeComponents::isoWeekNumber
int isoWeekNumber
Definition: kdatetimeparser_p.h:42
DateTimeComponents::dayInYear
int dayInYear
Definition: kdatetimeparser_p.h:41
DateTimeComponents::inputPosition
int inputPosition
Definition: kdatetimeparser_p.h:44
DateTimeComponents::dayOfIsoWeek
int dayOfIsoWeek
Definition: kdatetimeparser_p.h:43
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 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-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 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
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