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

Nepomuk-Core

  • sources
  • kde-4.12
  • kdelibs
  • nepomuk-core
  • libnepomukcore
  • query
dateparser.cpp
Go to the documentation of this file.
1 /*
2 * This file is part of the Nepomuk KDE project.
3 * Copyright (c) 2009 Adam Kidder <thekidder@gmail.com>
4 * Copyright (c) 2009 Sebastian Trueg <trueg@kde.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21 
22 #include "dateparser_p.h"
23 
24 #include <kdebug.h>
25 
26 #include <QtCore/QLocale>
27 #include <QtCore/QString>
28 #include <QtCore/QStringList>
29 #include <QtCore/QVector>
30 
31 
32 namespace {
33  //represents a time difference from the current time, to represent relative dates
34  struct time_difference
35  {
36  time_difference() : seconds(0), minutes(0), hours(0), days(0), weeks(0), months(0), years(0) {}
37  int seconds, minutes, hours, days, weeks, months, years;
38  };
39 
40  struct format
41  {
42  format() : pos(0) {}
43  format(const QRegExp& r, const QStringList& f) : regex(r), pos(0), useRelativeDate(false), formats(f) {}
44  format(const QRegExp& r, const time_difference& d, bool dr = false) : regex(r), pos(0), useRelativeDate(true), difference(d), dynamicRelative(dr) {}
45  QRegExp regex;
46  int pos;
47 
48  bool useRelativeDate;
49  time_difference difference;
50  bool dynamicRelative;
51  QStringList formats;
52  };
53 
54  struct date_string
55  {
56  QDate date;
57  unsigned int pos;
58  unsigned int length;
59  };
60 }
61 
62 class Nepomuk2::Search::DateParser::Private
63 {
64 public:
65  Private(const QString& text, unsigned int flags) :
66  m_text(text), m_locale(QLocale::English), m_flags(flags) {
67  //TODO: we are english-only here!
68  QStringList longMonthNames;
69  QStringList shortMonthNames;
70  for ( int i = 1; i <= 12; ++i ) {
71  longMonthNames << m_locale.monthName( i, QLocale::LongFormat );
72  shortMonthNames << m_locale.monthName( i, QLocale::ShortFormat );
73  }
74 
75  // DD.MM.YYYY
76  format date1( QRegExp( "\\b\\d{1,2}\\.\\d{1,2}\\.\\d{4,4}\\b" ), QStringList("d.M.yyyy") );
77 
78  // DD.MM.YY
79  format date2( QRegExp( "\\b\\d{1,2}\\.\\d{1,2}\\.\\d{2,2}\\b" ), QStringList("d.M.yy") );
80 
81  // MM/DD/YYYY
82  format date3( QRegExp( "\\b\\d{1,2}/\\d{1,2}/\\d{4,4}\\b" ), QStringList("M/d/yyyy") );
83 
84  // YYYY-MM-DD
85  format date13(QRegExp( "\\b\\d{4,4}-\\d{1,2}-\\d{1,2}\\b" ), QStringList("yyyy-M-d") );
86 
87  // MM/DD/YY
88  format date4( QRegExp( "\\b\\d{1,2}/\\d{1,2}/\\d{2,2}\\b" ), QStringList("M/d/yy") );
89 
90  // January MM [YYYY] (no word boundry at the end for 'st' or 'nd' or 'th') (also excluding ranges)
91  format date5( QRegExp( QString( "\\b(%1)\\s\\d{1,2}(?!(\\d|\\s?-\\s?\\d))(\\s\\d{4,4})?" ).arg( longMonthNames.join( "|" ) ) ),
92  QStringList("MMMM d") << QString("MMMM d yyyy") );
93 
94  // January, MM [YYYY] (no word boundry at the end for 'st' or 'nd' or 'th') (also excluding ranges)
95  format date6( QRegExp( QString( "\\b(%1),\\s?\\d{1,2}(?!(\\d|\\s?-\\s?\\d))(\\s\\d{4,4})?" ).arg( longMonthNames.join( "|" ) ) ),
96  QStringList("MMMM, d") << QString("MMMM,d") << QString("MMMM, d yyyy") << QString("MMMM,d yyyy") );
97 
98  // FIXME: trueg: IMHO something like "yesterday" should result in a range if not used with < or >.
99 
100  //TODO: english only again!
101  time_difference days;
102  days.days = -1;
103  format date7( QRegExp( QString( "\\b(yesterday)\\b" ) ), days );
104 
105  format date8( QRegExp( QString( "\\b(\\d{1,3}) (day)s? ago\\b" ) ), days, true );
106 
107  time_difference weeks;
108  weeks.weeks = -1;
109  format date9( QRegExp( QString( "\\ba week ago\\b" ) ), weeks );
110 
111  format date10( QRegExp( QString( "\\b(\\d{1,3}) (week)s? ago\\b" ) ), weeks, true );
112 
113  time_difference months;
114  months.months = -1;
115  format date11( QRegExp( QString( "\\ba month ago\\b" ) ), months );
116 
117  format date12( QRegExp( QString( "\\b(\\d{1,3}) (month)s? ago\\b" ) ), months, true );
118 
119  m_regexes.reserve( 13 );
120  m_regexes.push_back( date1 );
121  m_regexes.push_back( date2 );
122  m_regexes.push_back( date3 );
123  m_regexes.push_back( date4 );
124  m_regexes.push_back( date5 );
125  m_regexes.push_back( date6 );
126  m_regexes.push_back( date7 );
127  m_regexes.push_back( date8 );
128  m_regexes.push_back( date9 );
129  m_regexes.push_back( date10);
130  m_regexes.push_back( date11);
131  m_regexes.push_back( date12);
132  m_regexes.push_back( date13);
133  }
134 
135 
136  bool hasDate() {
137  if(!m_dates.empty()) return true;
138 
139  while(m_dates.empty() && !finishedParsing())
140  {
141  parseAllRegexes();
142  }
143 
144  if(!m_dates.empty()) return true;
145  return false;
146  }
147 
148 
149  QDate getDate() {
150  if( !m_dates.isEmpty() )
151  return m_dates.first().date;
152  else
153  return QDate();
154  }
155 
156  void next() {
157  m_dates.pop_front();
158  }
159 
160  unsigned int length() const {
161  if( !m_dates.isEmpty() )
162  return m_dates.first().length;
163  else
164  return 0;
165  }
166 
167  unsigned int pos() const {
168  if( !m_dates.isEmpty() )
169  return m_dates.first().pos;
170  else
171  return 0;
172  }
173  int dateObject;
174 
175 private:
176  bool finishedParsing() {
177  foreach(format r, m_regexes) {
178  if(r.pos != -1) return false;
179  }
180  return true;
181  }
182 
183 
184  void parseAllRegexes() {
185  QVector<format>::iterator it ;
186  for(it = m_regexes.begin(); it != m_regexes.end(); ++it) {
187  it->pos = it->regex.indexIn(m_text, it->pos);
188  if( it->pos == -1 )
189  continue;
190  if( !it->useRelativeDate && (m_flags & AbsoluteDates) ) {
191  foreach(QString format, it->formats) {
192  QDate date = m_locale.toDate( it->regex.cap( 0 ), format );
193  if(date.isValid()) {
194  if(!format.contains( "yy" ) )
195  date.setDate( QDate::currentDate().year(), date.month(), date.day() );
196  kDebug() << "Found absolute date:" << date;
197  date_string dateObject;
198  dateObject.date = date;
199  dateObject.pos = it->pos;
200  dateObject.length = it->regex.matchedLength();
201  m_dates.append( dateObject );
202  break;
203  }
204  }
205  }
206  else if( m_flags & RelativeDates) {
207  int amount = 1;
208  if( it->dynamicRelative ) {
209  amount = it->regex.cap( 1 ).toInt();
210  kDebug() << "dynamic relative date, amount is" << amount << it->regex.cap( 1 );
211  }
212  QDate current( QDate::currentDate() );
213  current = current.addDays( it->difference.days * amount );
214  current = current.addDays( it->difference.weeks * 7 * amount );
215  current = current.addMonths( it->difference.months * amount );
216  current = current.addYears( it->difference.years * amount );
217 
218  kDebug() << "Found relative date:" << current << it->regex.pattern();
219  date_string dateObject;
220  dateObject.date = current;
221  dateObject.pos = it->pos;
222  dateObject.length = it->regex.matchedLength();
223  m_dates.append( dateObject );
224  }
225  }
226  }
227 
228 
229  const QString& m_text;
230  QLocale m_locale;
231  QVector<format> m_regexes;
232  QList<date_string> m_dates;
233  unsigned int m_flags;
234 };
235 
236 
237 
238 Nepomuk2::Search::DateParser::DateParser(const QString& text, unsigned int flags) :
239  d( new Private(text, flags) ) {
240 }
241 
242 
243 Nepomuk2::Search::DateParser::~DateParser() {
244  delete d;
245 }
246 
247 bool Nepomuk2::Search::DateParser::hasDate() {
248  return d->hasDate();
249 }
250 
251 QDate Nepomuk2::Search::DateParser::getDate() {
252  return d->getDate();
253 }
254 
255 void Nepomuk2::Search::DateParser::next() {
256  d->next();
257 }
258 
259 unsigned int Nepomuk2::Search::DateParser::pos() const {
260  return d->pos();
261 }
262 
263 unsigned int Nepomuk2::Search::DateParser::length() const {
264  return d->length();
265 }
266 
267 class Nepomuk2::Search::TimeParser::Private
268 {
269 public:
270  Private(const QString& text) : m_text(text), m_locale(QLocale::English) {
271  // hh:mm[pm|am]
272  format time1( QRegExp( "\\b\\d{1,2}\\:\\d{2,2}\\s?(pm|am|AM|PM)?\\b" ), QStringList("h:map") << QString("h:m ap") );
273 
274  // hh:mm
275  format time2( QRegExp( "\\b\\d{1,2}\\:\\d{2,2}\\b(?!\\s?(pm|am|AM|PM))\\b" ), QStringList("h:m") );
276 
277  m_regexes.push_back( time1 );
278  m_regexes.push_back( time2 );
279  }
280 
281 
282  bool hasTime() {
283  if(!m_times.empty()) return true;
284 
285  while(m_times.empty() && !finishedParsing())
286  {
287  parseAllRegexes();
288  }
289 
290  if(!m_times.empty()) return true;
291  return false;
292  }
293 
294 
295  QTime next() {
296  return m_times.takeFirst();
297  }
298 private:
299  bool finishedParsing() {
300  foreach(format r, m_regexes) {
301  if(r.pos != -1) return false;
302  }
303  return true;
304  }
305 
306 
307  void parseAllRegexes() {
308  QVector<format>::iterator it ;
309  for(it = m_regexes.begin(); it != m_regexes.end(); ++it) {
310  it->pos = it->regex.indexIn(m_text, it->pos);
311  if( !it->useRelativeDate ) {
312  foreach(QString format, it->formats) {
313  QTime time = m_locale.toTime( it->regex.cap( 0 ), format );
314  if(time.isValid()) {
315  kDebug() << "Found time:" << time;
316  m_times.append( time );
317  break;
318  }
319  }
320  }
321  else {
322  QTime current( QTime::currentTime() );
323  current.addSecs( it->difference.seconds );
324  current.addSecs( it->difference.minutes * 60 );
325  current.addSecs( it->difference.hours * 60 * 60 );
326 
327  kDebug() << "Found time:" << current;
328  m_times.append( current );
329  break;
330  }
331  }
332  }
333 
334 
335  const QString& m_text;
336  QLocale m_locale;
337  QVector<format> m_regexes;
338  QList<QTime> m_times;
339 };
340 
341 
342 
343 Nepomuk2::Search::TimeParser::TimeParser(const QString& text) : d( new Private(text) ) {
344 }
345 
346 
347 Nepomuk2::Search::TimeParser::~TimeParser() {
348  delete d;
349 }
350 
351 bool Nepomuk2::Search::TimeParser::hasTime() {
352  return d->hasTime();
353 }
354 
355 QTime Nepomuk2::Search::TimeParser::next() {
356  return d->next();
357 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:48:08 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Nepomuk-Core

Skip menu "Nepomuk-Core"
  • 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