QGIS API Documentation 3.99.0-Master (d270888f95f)
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}
43
44QgsInterval::QgsInterval( std::chrono::milliseconds milliseconds )
45 : mSeconds( static_cast<double>( milliseconds.count() ) / 1000.0 )
46 , mValid( true )
47 , mOriginalDuration( static_cast<double>( milliseconds.count() ) )
48 , mOriginalUnit( Qgis::TemporalUnit::Milliseconds )
49{
50}
51
53 : mSeconds( duration * QgsUnitTypes::fromUnitToUnitFactor( unit, Qgis::TemporalUnit::Seconds ) )
54 , mValid( true )
55 , mOriginalDuration( duration )
56 , mOriginalUnit( unit )
57{
58}
59
60QgsInterval::QgsInterval( double years, double months, double weeks, double days, double hours, double minutes, double seconds )
61 : mSeconds( years * QgsUnitTypes::fromUnitToUnitFactor( Qgis::TemporalUnit::Years, Qgis::TemporalUnit::Seconds )
62 + months * QgsUnitTypes::fromUnitToUnitFactor( Qgis::TemporalUnit::Months, Qgis::TemporalUnit::Seconds )
63 + weeks * QgsUnitTypes::fromUnitToUnitFactor( Qgis::TemporalUnit::Weeks, Qgis::TemporalUnit::Seconds )
64 + days * QgsUnitTypes::fromUnitToUnitFactor( Qgis::TemporalUnit::Days, Qgis::TemporalUnit::Seconds )
65 + hours * QgsUnitTypes::fromUnitToUnitFactor( Qgis::TemporalUnit::Hours, Qgis::TemporalUnit::Seconds )
66 + minutes * QgsUnitTypes::fromUnitToUnitFactor( Qgis::TemporalUnit::Minutes, Qgis::TemporalUnit::Seconds )
67 + seconds )
68 , mValid( true )
69{
70 if ( years && !months && !weeks && !days && !hours && !minutes && !seconds )
71 {
72 mOriginalDuration = years;
73 mOriginalUnit = Qgis::TemporalUnit::Years;
74 }
75 else if ( !years && months && !weeks && !days && !hours && !minutes && !seconds )
76 {
77 mOriginalDuration = months;
78 mOriginalUnit = Qgis::TemporalUnit::Months;
79 }
80 else if ( !years && !months && weeks && !days && !hours && !minutes && !seconds )
81 {
82 mOriginalDuration = weeks;
83 mOriginalUnit = Qgis::TemporalUnit::Weeks;
84 }
85 else if ( !years && !months && !weeks && days && !hours && !minutes && !seconds )
86 {
87 mOriginalDuration = days;
88 mOriginalUnit = Qgis::TemporalUnit::Days;
89 }
90 else if ( !years && !months && !weeks && !days && hours && !minutes && !seconds )
91 {
92 mOriginalDuration = hours;
93 mOriginalUnit = Qgis::TemporalUnit::Hours;
94 }
95 else if ( !years && !months && !weeks && !days && !hours && minutes && !seconds )
96 {
97 mOriginalDuration = minutes;
98 mOriginalUnit = Qgis::TemporalUnit::Minutes;
99 }
100 else if ( !years && !months && !weeks && !days && !hours && !minutes && seconds )
101 {
102 mOriginalDuration = seconds;
103 mOriginalUnit = Qgis::TemporalUnit::Seconds;
104 }
105 else if ( !years && !months && !weeks && !days && !hours && !minutes && !seconds )
106 {
107 mOriginalDuration = 0;
108 mOriginalUnit = Qgis::TemporalUnit::Seconds;
109 }
110 else
111 {
112 mOriginalUnit = Qgis::TemporalUnit::Unknown;
113 }
114}
115
116double QgsInterval::years() const
117{
118 if ( mOriginalUnit == Qgis::TemporalUnit::Years )
119 return mOriginalDuration;
120
121 return mSeconds / YEARS;
122}
123
125{
126 mSeconds = years * YEARS;
127 mValid = true;
128 mOriginalDuration = years;
129 mOriginalUnit = Qgis::TemporalUnit::Years;
130}
131
133{
134 if ( mOriginalUnit == Qgis::TemporalUnit::Months )
135 return mOriginalDuration;
136
137 return mSeconds / MONTHS;
138}
139
141{
142 mSeconds = months * MONTHS;
143 mValid = true;
144 mOriginalDuration = months;
145 mOriginalUnit = Qgis::TemporalUnit::Months;
146}
147
148double QgsInterval::weeks() const
149{
150 if ( mOriginalUnit == Qgis::TemporalUnit::Weeks )
151 return mOriginalDuration;
152
153 return mSeconds / WEEKS;
154}
155
156
158{
159 mSeconds = weeks * WEEKS;
160 mValid = true;
161 mOriginalDuration = weeks;
162 mOriginalUnit = Qgis::TemporalUnit::Weeks;
163}
164
165double QgsInterval::days() const
166{
167 if ( mOriginalUnit == Qgis::TemporalUnit::Days )
168 return mOriginalDuration;
169
170 return mSeconds / DAY;
171}
172
173
175{
176 mSeconds = days * DAY;
177 mValid = true;
178 mOriginalDuration = days;
179 mOriginalUnit = Qgis::TemporalUnit::Days;
180}
181
182double QgsInterval::hours() const
183{
184 if ( mOriginalUnit == Qgis::TemporalUnit::Hours )
185 return mOriginalDuration;
186
187 return mSeconds / HOUR;
188}
189
190
192{
193 mSeconds = hours * HOUR;
194 mValid = true;
195 mOriginalDuration = hours;
196 mOriginalUnit = Qgis::TemporalUnit::Hours;
197}
198
200{
201 if ( mOriginalUnit == Qgis::TemporalUnit::Minutes )
202 return mOriginalDuration;
203
204 return mSeconds / MINUTE;
205}
206
208{
209 mSeconds = minutes * MINUTE;
210 mValid = true;
211 mOriginalDuration = minutes;
212 mOriginalUnit = Qgis::TemporalUnit::Minutes;
213}
214
216{
217 mSeconds = seconds;
218 mValid = true;
219 mOriginalDuration = seconds;
220 mOriginalUnit = Qgis::TemporalUnit::Seconds;
221}
222
223QgsInterval QgsInterval::fromString( const QString &string )
224{
225 double seconds = 0;
226 const thread_local QRegularExpression rx( "([-+]?\\d*\\.?\\d+\\s+\\S+)", QRegularExpression::CaseInsensitiveOption );
227 const thread_local QRegularExpression rxtime( ".* \\d{1,2}(:)\\d{1,2}(:)\\d{1,2}.*", QRegularExpression::CaseInsensitiveOption );
228
229 const QRegularExpressionMatch matchtime = rxtime.match( string );
230 QString modedString = QString( string );
231 if ( matchtime.hasMatch() ) //some part of the string contains 00:00:00 style duration
232 {
233 // Get the second occurrence of : (minutes)
234 modedString.replace( matchtime.capturedStart( 2 ), 1, " minutes " );
235 // Get the first occurrence of : (hours)
236 modedString.replace( matchtime.capturedStart( 1 ), 1, " hours " );
237 modedString.append( " seconds" );
238 }
239
240 QStringList list;
241 int pos = 0;
242 QRegularExpressionMatch match = rx.match( modedString );
243 while ( match.hasMatch() )
244 {
245 list << match.captured( 1 );
246 pos = match.capturedStart() + match.capturedLength();
247 match = rx.match( modedString, pos );
248 }
249
250 const thread_local QMap<int, QStringList> map{{
251 {1, QStringList() << u"second"_s << u"seconds"_s << QObject::tr( "second|seconds", "list of words separated by | which reference years" ).split( '|' )},
252 { 0 + MINUTE, QStringList() << u"minute"_s << u"minutes"_s << QObject::tr( "minute|minutes", "list of words separated by | which reference minutes" ).split( '|' ) },
253 {0 + HOUR, QStringList() << u"hour"_s << u"hours"_s << QObject::tr( "hour|hours", "list of words separated by | which reference minutes hours" ).split( '|' )},
254 {0 + DAY, QStringList() << u"day"_s << u"days"_s << QObject::tr( "day|days", "list of words separated by | which reference days" ).split( '|' )},
255 {0 + WEEKS, QStringList() << u"week"_s << u"weeks"_s << QObject::tr( "week|weeks", "wordlist separated by | which reference weeks" ).split( '|' )},
256 {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( '|' )},
257 {0 + YEARS, QStringList() << u"year"_s << u"years"_s << QObject::tr( "year|years", "list of words separated by | which reference years" ).split( '|' )},
258 }};
259
260 const thread_local QRegularExpression splitRx( "\\s+" );
261
262 for ( const QString &match : std::as_const( list ) )
263 {
264 const QStringList split = match.split( splitRx );
265 bool ok;
266 const double value = split.at( 0 ).toDouble( &ok );
267 if ( !ok )
268 {
269 continue;
270 }
271
272 bool matched = false;
273 QMap<int, QStringList>::const_iterator it = map.constBegin();
274 for ( ; it != map.constEnd(); ++it )
275 {
276 const int duration = it.key();
277 const QStringList durationIdentifiers = it.value();
278 for ( const QString &identifier : durationIdentifiers )
279 {
280 if ( match.contains( identifier, Qt::CaseInsensitive ) )
281 {
282 matched = true;
283 break;
284 }
285 }
286
287 if ( matched )
288 {
289 seconds += value * duration;
290 break;
291 }
292 }
293 }
294
295 // If we can't parse the string at all then we just return invalid
296 if ( seconds == 0 )
297 return QgsInterval();
298
299 return QgsInterval( seconds );
300}
301
302QDebug operator<<( QDebug dbg, const QgsInterval &interval )
303{
304 if ( !interval.isValid() )
305 dbg.nospace() << "QgsInterval()";
306 else
307 dbg.nospace() << "QgsInterval(" << interval.seconds() << ")";
308 return dbg.maybeSpace();
309}
310
311#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
312
313QgsInterval operator-( const QDateTime &dt1, const QDateTime &dt2 )
314{
315 const qint64 mSeconds = dt2.msecsTo( dt1 );
316 return QgsInterval( mSeconds / 1000.0 );
317}
318
319#endif
320
321QDateTime operator+( const QDateTime &start, const QgsInterval &interval )
322{
323 return start.addMSecs( static_cast<qint64>( interval.seconds() * 1000.0 ) );
324}
325
326QgsInterval operator-( QDate date1, QDate date2 )
327{
328 const qint64 seconds = static_cast< qint64 >( date2.daysTo( date1 ) ) * 24 * 60 * 60;
329 return QgsInterval( seconds );
330}
331
332QgsInterval operator-( QTime time1, QTime time2 )
333{
334 const qint64 mSeconds = time2.msecsTo( time1 );
335 return QgsInterval( mSeconds / 1000.0 );
336}
337
Provides global constants and enumerations for use throughout the application.
Definition qgis.h:59
TemporalUnit
Temporal units.
Definition qgis.h:5231
@ Hours
Hours.
Definition qgis.h:5235
@ Unknown
Unknown time unit.
Definition qgis.h:5243
@ Seconds
Seconds.
Definition qgis.h:5233
@ Weeks
Weeks.
Definition qgis.h:5237
@ Years
Years.
Definition qgis.h:5239
@ Months
Months.
Definition qgis.h:5238
@ Minutes
Minutes.
Definition qgis.h:5234
A representation of the interval between two datetime values.
Definition qgsinterval.h:50
static const int MINUTE
Seconds per minute.
Definition qgsinterval.h:66
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:58
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:64
static const int WEEKS
Seconds per week.
Definition qgsinterval.h:60
static const int DAY
Seconds per day.
Definition qgsinterval.h:62
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:56
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.