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