22 #include "dateparser_p.h"
26 #include <QtCore/QLocale>
27 #include <QtCore/QString>
28 #include <QtCore/QStringList>
29 #include <QtCore/QVector>
34 struct time_difference
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;
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) {}
49 time_difference difference;
62 class Nepomuk2::Search::DateParser::Private
65 Private(
const QString& text,
unsigned int flags) :
66 m_text(text), m_locale(QLocale::English), m_flags(flags) {
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 );
76 format date1( QRegExp(
"\\b\\d{1,2}\\.\\d{1,2}\\.\\d{4,4}\\b" ), QStringList(
"d.M.yyyy") );
79 format date2( QRegExp(
"\\b\\d{1,2}\\.\\d{1,2}\\.\\d{2,2}\\b" ), QStringList(
"d.M.yy") );
82 format date3( QRegExp(
"\\b\\d{1,2}/\\d{1,2}/\\d{4,4}\\b" ), QStringList(
"M/d/yyyy") );
85 format date13(QRegExp(
"\\b\\d{4,4}-\\d{1,2}-\\d{1,2}\\b" ), QStringList(
"yyyy-M-d") );
88 format date4( QRegExp(
"\\b\\d{1,2}/\\d{1,2}/\\d{2,2}\\b" ), QStringList(
"M/d/yy") );
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") );
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") );
101 time_difference days;
103 format date7( QRegExp( QString(
"\\b(yesterday)\\b" ) ), days );
105 format date8( QRegExp( QString(
"\\b(\\d{1,3}) (day)s? ago\\b" ) ), days,
true );
107 time_difference weeks;
109 format date9( QRegExp( QString(
"\\ba week ago\\b" ) ), weeks );
111 format date10( QRegExp( QString(
"\\b(\\d{1,3}) (week)s? ago\\b" ) ), weeks,
true );
113 time_difference months;
115 format date11( QRegExp( QString(
"\\ba month ago\\b" ) ), months );
117 format date12( QRegExp( QString(
"\\b(\\d{1,3}) (month)s? ago\\b" ) ), months,
true );
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);
137 if(!m_dates.empty())
return true;
139 while(m_dates.empty() && !finishedParsing())
144 if(!m_dates.empty())
return true;
150 if( !m_dates.isEmpty() )
151 return m_dates.first().date;
160 unsigned int length()
const {
161 if( !m_dates.isEmpty() )
162 return m_dates.first().length;
167 unsigned int pos()
const {
168 if( !m_dates.isEmpty() )
169 return m_dates.first().pos;
176 bool finishedParsing() {
177 foreach(format r, m_regexes) {
178 if(r.pos != -1)
return false;
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);
190 if( !it->useRelativeDate && (m_flags & AbsoluteDates) ) {
191 foreach(QString format, it->formats) {
192 QDate date = m_locale.toDate( it->regex.cap( 0 ), format );
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 );
206 else if( m_flags & RelativeDates) {
208 if( it->dynamicRelative ) {
209 amount = it->regex.cap( 1 ).toInt();
210 kDebug() <<
"dynamic relative date, amount is" << amount << it->regex.cap( 1 );
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 );
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 );
229 const QString& m_text;
231 QVector<format> m_regexes;
232 QList<date_string> m_dates;
233 unsigned int m_flags;
238 Nepomuk2::Search::DateParser::DateParser(
const QString& text,
unsigned int flags) :
239 d( new Private(text, flags) ) {
243 Nepomuk2::Search::DateParser::~DateParser() {
247 bool Nepomuk2::Search::DateParser::hasDate() {
251 QDate Nepomuk2::Search::DateParser::getDate() {
255 void Nepomuk2::Search::DateParser::next() {
259 unsigned int Nepomuk2::Search::DateParser::pos()
const {
263 unsigned int Nepomuk2::Search::DateParser::length()
const {
267 class Nepomuk2::Search::TimeParser::Private
270 Private(
const QString& text) : m_text(text), m_locale(QLocale::English) {
272 format time1( QRegExp(
"\\b\\d{1,2}\\:\\d{2,2}\\s?(pm|am|AM|PM)?\\b" ), QStringList(
"h:map") << QString(
"h:m ap") );
275 format time2( QRegExp(
"\\b\\d{1,2}\\:\\d{2,2}\\b(?!\\s?(pm|am|AM|PM))\\b" ), QStringList(
"h:m") );
277 m_regexes.push_back( time1 );
278 m_regexes.push_back( time2 );
283 if(!m_times.empty())
return true;
285 while(m_times.empty() && !finishedParsing())
290 if(!m_times.empty())
return true;
296 return m_times.takeFirst();
299 bool finishedParsing() {
300 foreach(format r, m_regexes) {
301 if(r.pos != -1)
return false;
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 );
315 kDebug() <<
"Found time:" << time;
316 m_times.append( time );
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 );
327 kDebug() <<
"Found time:" << current;
328 m_times.append( current );
335 const QString& m_text;
337 QVector<format> m_regexes;
338 QList<QTime> m_times;
343 Nepomuk2::Search::TimeParser::TimeParser(
const QString& text) : d( new Private(text) ) {
347 Nepomuk2::Search::TimeParser::~TimeParser() {
351 bool Nepomuk2::Search::TimeParser::hasTime() {
355 QTime Nepomuk2::Search::TimeParser::next() {