QGIS API Documentation 4.1.0-Master (60fea48833c)
Loading...
Searching...
No Matches
qgsinterval.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsinterval.cpp
3 ---------------
4 Date : May 2016
5 Copyright : (C) 2016 by Nyall Dawson
6 Email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include "qgsinterval.h"
17
18#include "qgsunittypes.h"
19
20#include <QDateTime>
21#include <QDebug>
22#include <QMap>
23#include <QObject>
24#include <QRegularExpression>
25#include <QString>
26#include <QStringList>
27
28using namespace Qt::StringLiterals;
29
30/***************************************************************************
31 * This class is considered CRITICAL and any change MUST be accompanied with
32 * full unit tests in test_qgsinterval.py.
33 * See details in QEP #17
34 ****************************************************************************/
35
37 : mSeconds( seconds )
38 , mValid( true )
39 , mOriginalDuration( seconds )
40 , mOriginalUnit( Qgis::TemporalUnit::Seconds )
41{}
42
43QgsInterval::QgsInterval( std::chrono::milliseconds milliseconds )
44 : mSeconds( static_cast<double>( milliseconds.count() ) / 1000.0 )
45 , mValid( true )
46 , mOriginalDuration( static_cast<double>( milliseconds.count() ) )
47 , mOriginalUnit( Qgis::TemporalUnit::Milliseconds )
48{}
49
51 : mSeconds( duration * QgsUnitTypes::fromUnitToUnitFactor( unit, Qgis::TemporalUnit::Seconds ) )
52 , mValid( true )
53 , mOriginalDuration( duration )
54 , mOriginalUnit( unit )
55{}
56
57QgsInterval::QgsInterval( double years, double months, double weeks, double days, double hours, double minutes, double seconds )
58 : mSeconds(
59 years * QgsUnitTypes::fromUnitToUnitFactor( Qgis::TemporalUnit::Years, Qgis::TemporalUnit::Seconds )
60 + months * QgsUnitTypes::fromUnitToUnitFactor( Qgis::TemporalUnit::Months, Qgis::TemporalUnit::Seconds )
61 + weeks * QgsUnitTypes::fromUnitToUnitFactor( Qgis::TemporalUnit::Weeks, Qgis::TemporalUnit::Seconds )
62 + days * QgsUnitTypes::fromUnitToUnitFactor( Qgis::TemporalUnit::Days, Qgis::TemporalUnit::Seconds )
63 + hours * QgsUnitTypes::fromUnitToUnitFactor( Qgis::TemporalUnit::Hours, Qgis::TemporalUnit::Seconds )
64 + minutes * QgsUnitTypes::fromUnitToUnitFactor( Qgis::TemporalUnit::Minutes, Qgis::TemporalUnit::Seconds )
65 + seconds
66 )
67 , mValid( true )
68{
69 if ( years && !months && !weeks && !days && !hours && !minutes && !seconds )
70 {
71 mOriginalDuration = years;
72 mOriginalUnit = Qgis::TemporalUnit::Years;
73 }
74 else if ( !years && months && !weeks && !days && !hours && !minutes && !seconds )
75 {
76 mOriginalDuration = months;
77 mOriginalUnit = Qgis::TemporalUnit::Months;
78 }
79 else if ( !years && !months && weeks && !days && !hours && !minutes && !seconds )
80 {
81 mOriginalDuration = weeks;
82 mOriginalUnit = Qgis::TemporalUnit::Weeks;
83 }
84 else if ( !years && !months && !weeks && days && !hours && !minutes && !seconds )
85 {
86 mOriginalDuration = days;
87 mOriginalUnit = Qgis::TemporalUnit::Days;
88 }
89 else if ( !years && !months && !weeks && !days && hours && !minutes && !seconds )
90 {
91 mOriginalDuration = hours;
92 mOriginalUnit = Qgis::TemporalUnit::Hours;
93 }
94 else if ( !years && !months && !weeks && !days && !hours && minutes && !seconds )
95 {
96 mOriginalDuration = minutes;
97 mOriginalUnit = Qgis::TemporalUnit::Minutes;
98 }
99 else if ( !years && !months && !weeks && !days && !hours && !minutes && seconds )
100 {
101 mOriginalDuration = seconds;
102 mOriginalUnit = Qgis::TemporalUnit::Seconds;
103 }
104 else if ( !years && !months && !weeks && !days && !hours && !minutes && !seconds )
105 {
106 mOriginalDuration = 0;
107 mOriginalUnit = Qgis::TemporalUnit::Seconds;
108 }
109 else
110 {
111 mOriginalUnit = Qgis::TemporalUnit::Unknown;
112 }
113}
114
115double QgsInterval::years() const
116{
117 if ( mOriginalUnit == Qgis::TemporalUnit::Years )
118 return mOriginalDuration;
119
120 return mSeconds / YEARS;
121}
122
124{
125 mSeconds = years * YEARS;
126 mValid = true;
127 mOriginalDuration = years;
128 mOriginalUnit = Qgis::TemporalUnit::Years;
129}
130
132{
133 if ( mOriginalUnit == Qgis::TemporalUnit::Months )
134 return mOriginalDuration;
135
136 return mSeconds / MONTHS;
137}
138
140{
141 mSeconds = months * MONTHS;
142 mValid = true;
143 mOriginalDuration = months;
144 mOriginalUnit = Qgis::TemporalUnit::Months;
145}
146
147double QgsInterval::weeks() const
148{
149 if ( mOriginalUnit == Qgis::TemporalUnit::Weeks )
150 return mOriginalDuration;
151
152 return mSeconds / WEEKS;
153}
154
155
157{
158 mSeconds = weeks * WEEKS;
159 mValid = true;
160 mOriginalDuration = weeks;
161 mOriginalUnit = Qgis::TemporalUnit::Weeks;
162}
163
164double QgsInterval::days() const
165{
166 if ( mOriginalUnit == Qgis::TemporalUnit::Days )
167 return mOriginalDuration;
168
169 return mSeconds / DAY;
170}
171
172
174{
175 mSeconds = days * DAY;
176 mValid = true;
177 mOriginalDuration = days;
178 mOriginalUnit = Qgis::TemporalUnit::Days;
179}
180
181double QgsInterval::hours() const
182{
183 if ( mOriginalUnit == Qgis::TemporalUnit::Hours )
184 return mOriginalDuration;
185
186 return mSeconds / HOUR;
187}
188
189
191{
192 mSeconds = hours * HOUR;
193 mValid = true;
194 mOriginalDuration = hours;
195 mOriginalUnit = Qgis::TemporalUnit::Hours;
196}
197
199{
200 if ( mOriginalUnit == Qgis::TemporalUnit::Minutes )
201 return mOriginalDuration;
202
203 return mSeconds / MINUTE;
204}
205
207{
208 mSeconds = minutes * MINUTE;
209 mValid = true;
210 mOriginalDuration = minutes;
211 mOriginalUnit = Qgis::TemporalUnit::Minutes;
212}
213
215{
216 mSeconds = seconds;
217 mValid = true;
218 mOriginalDuration = seconds;
219 mOriginalUnit = Qgis::TemporalUnit::Seconds;
220}
221
222QgsInterval QgsInterval::fromString( const QString &string )
223{
224 double seconds = 0;
225 const thread_local QRegularExpression rx( "([-+]?\\d*\\.?\\d+\\s+\\S+)", QRegularExpression::CaseInsensitiveOption );
226 const thread_local QRegularExpression rxtime( ".* \\d{1,2}(:)\\d{1,2}(:)\\d{1,2}.*", QRegularExpression::CaseInsensitiveOption );
227
228 const QRegularExpressionMatch matchtime = rxtime.match( string );
229 QString modedString = QString( string );
230 if ( matchtime.hasMatch() ) //some part of the string contains 00:00:00 style duration
231 {
232 // Get the second occurrence of : (minutes)
233 modedString.replace( matchtime.capturedStart( 2 ), 1, " minutes " );
234 // Get the first occurrence of : (hours)
235 modedString.replace( matchtime.capturedStart( 1 ), 1, " hours " );
236 modedString.append( " seconds" );
237 }
238
239 QStringList list;
240 int pos = 0;
241 QRegularExpressionMatch match = rx.match( modedString );
242 while ( match.hasMatch() )
243 {
244 list << match.captured( 1 );
245 pos = match.capturedStart() + match.capturedLength();
246 match = rx.match( modedString, pos );
247 }
248
249 const thread_local QMap<int, QStringList> map { {
250 { 1, QStringList() << u"second"_s << u"seconds"_s << QObject::tr( "second|seconds", "list of words separated by | which reference years" ).split( '|' ) },
251 { 0 + MINUTE, QStringList() << u"minute"_s << u"minutes"_s << QObject::tr( "minute|minutes", "list of words separated by | which reference minutes" ).split( '|' ) },
252 { 0 + HOUR, QStringList() << u"hour"_s << u"hours"_s << QObject::tr( "hour|hours", "list of words separated by | which reference minutes hours" ).split( '|' ) },
253 { 0 + DAY, QStringList() << u"day"_s << u"days"_s << QObject::tr( "day|days", "list of words separated by | which reference days" ).split( '|' ) },
254 { 0 + WEEKS, QStringList() << u"week"_s << u"weeks"_s << QObject::tr( "week|weeks", "wordlist separated by | which reference weeks" ).split( '|' ) },
255 { 0 + MONTHS, QStringList() << u"month"_s << u"months"_s << u"mon"_s << QObject::tr( "month|months|mon", "list of words separated by | which reference months" ).split( '|' ) },
256 { 0 + YEARS, QStringList() << u"year"_s << u"years"_s << QObject::tr( "year|years", "list of words separated by | which reference years" ).split( '|' ) },
257 } };
258
259 const thread_local QRegularExpression splitRx( "\\s+" );
260
261 for ( const QString &match : std::as_const( list ) )
262 {
263 const QStringList split = match.split( splitRx );
264 bool ok;
265 const double value = split.at( 0 ).toDouble( &ok );
266 if ( !ok )
267 {
268 continue;
269 }
270
271 bool matched = false;
272 QMap<int, QStringList>::const_iterator it = map.constBegin();
273 for ( ; it != map.constEnd(); ++it )
274 {
275 const int duration = it.key();
276 const QStringList durationIdentifiers = it.value();
277 for ( const QString &identifier : durationIdentifiers )
278 {
279 if ( match.contains( identifier, Qt::CaseInsensitive ) )
280 {
281 matched = true;
282 break;
283 }
284 }
285
286 if ( matched )
287 {
288 seconds += value * duration;
289 break;
290 }
291 }
292 }
293
294 // If we can't parse the string at all then we just return invalid
295 if ( seconds == 0 )
296 return QgsInterval();
297
298 return QgsInterval( seconds );
299}
300
301QDebug operator<<( QDebug dbg, const QgsInterval &interval )
302{
303 if ( !interval.isValid() )
304 dbg.nospace() << "QgsInterval()";
305 else
306 dbg.nospace() << "QgsInterval(" << interval.seconds() << ")";
307 return dbg.maybeSpace();
308}
309
310QDateTime operator+( const QDateTime &start, const QgsInterval &interval )
311{
312 return start.addMSecs( static_cast<qint64>( interval.seconds() * 1000.0 ) );
313}
314
315QgsInterval operator-( QDate date1, QDate date2 )
316{
317 const qint64 seconds = static_cast< qint64 >( date2.daysTo( date1 ) ) * 24 * 60 * 60;
318 return QgsInterval( seconds );
319}
320
321QgsInterval operator-( QTime time1, QTime time2 )
322{
323 const qint64 mSeconds = time2.msecsTo( time1 );
324 return QgsInterval( mSeconds / 1000.0 );
325}
Provides global constants and enumerations for use throughout the application.
Definition qgis.h:62
TemporalUnit
Temporal units.
Definition qgis.h:5316
@ Hours
Hours.
Definition qgis.h:5320
@ Unknown
Unknown time unit.
Definition qgis.h:5328
@ Seconds
Seconds.
Definition qgis.h:5318
@ Weeks
Weeks.
Definition qgis.h:5322
@ Years
Years.
Definition qgis.h:5324
@ Months
Months.
Definition qgis.h:5323
@ Minutes
Minutes.
Definition qgis.h:5319
A representation of the interval between two datetime values.
Definition qgsinterval.h:52
static const int MINUTE
Seconds per minute.
Definition qgsinterval.h:67
bool isValid() const
Returns true if the interval is valid.
double days() const
Returns the interval duration in days.
void setMinutes(double minutes)
Sets the interval duration in minutes.
void setWeeks(double weeks)
Sets the interval duration in weeks.
QgsInterval()=default
Default constructor for QgsInterval.
double weeks() const
Returns the interval duration in weeks.
static const int MONTHS
Seconds per month, based on 30 day month.
Definition qgsinterval.h:59
double months() const
Returns the interval duration in months (based on a 30 day month).
static QgsInterval fromString(const QString &string)
Converts a string to an interval.
double seconds() const
Returns the interval duration in seconds.
double years() const
Returns the interval duration in years (based on an average year length).
static const int HOUR
Seconds per hour.
Definition qgsinterval.h:65
static const int WEEKS
Seconds per week.
Definition qgsinterval.h:61
static const int DAY
Seconds per day.
Definition qgsinterval.h:63
double hours() const
Returns the interval duration in hours.
void setHours(double hours)
Sets the interval duration in hours.
static const int YEARS
Seconds per year (average).
Definition qgsinterval.h:57
void setYears(double years)
Sets the interval duration in years.
void setSeconds(double seconds)
Sets the interval duration in seconds.
void setDays(double days)
Sets the interval duration in days.
double minutes() const
Returns the interval duration in minutes.
void setMonths(double months)
Sets the interval duration in months.
Helper functions for various unit types.
QDebug operator<<(QDebug dbg, const QgsInterval &interval)
Debug string representation of interval.
QgsInterval operator-(QDate date1, QDate date2)
Returns the interval between two dates.
QDateTime operator+(const QDateTime &start, const QgsInterval &interval)
Adds an interval to a datetime.