QGIS API Documentation  3.20.0-Odense (decaadbb31)
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 #include <QString>
18 #include <QStringList>
19 #include <QMap>
20 #include <QObject>
21 #include <QDebug>
22 #include <QDateTime>
23 
24 /***************************************************************************
25  * This class is considered CRITICAL and any change MUST be accompanied with
26  * full unit tests in test_qgsinterval.py.
27  * See details in QEP #17
28  ****************************************************************************/
29 
30 QgsInterval::QgsInterval( double seconds )
31  : mSeconds( seconds )
32  , mValid( true )
33  , mOriginalDuration( seconds )
34  , mOriginalUnit( QgsUnitTypes::TemporalSeconds )
35 {
36 }
37 
39  : mSeconds( duration * QgsUnitTypes::fromUnitToUnitFactor( unit, QgsUnitTypes::TemporalSeconds ) )
40  , mValid( true )
41  , mOriginalDuration( duration )
42  , mOriginalUnit( unit )
43 {
44 }
45 
46 QgsInterval::QgsInterval( double years, double months, double weeks, double days, double hours, double minutes, double seconds )
47  : mSeconds( years * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::TemporalYears, QgsUnitTypes::TemporalSeconds )
48  + months * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::TemporalMonths, QgsUnitTypes::TemporalSeconds )
49  + weeks * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::TemporalWeeks, QgsUnitTypes::TemporalSeconds )
50  + days * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::TemporalDays, QgsUnitTypes::TemporalSeconds )
51  + hours * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::TemporalHours, QgsUnitTypes::TemporalSeconds )
52  + minutes * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::TemporalMinutes, QgsUnitTypes::TemporalSeconds )
53  + seconds )
54  , mValid( true )
55 {
56  if ( years && !months && !weeks && !days && !hours && !minutes && !seconds )
57  {
58  mOriginalDuration = years;
59  mOriginalUnit = QgsUnitTypes::TemporalYears;
60  }
61  else if ( !years && months && !weeks && !days && !hours && !minutes && !seconds )
62  {
63  mOriginalDuration = months;
64  mOriginalUnit = QgsUnitTypes::TemporalMonths;
65  }
66  else if ( !years && !months && weeks && !days && !hours && !minutes && !seconds )
67  {
68  mOriginalDuration = weeks;
69  mOriginalUnit = QgsUnitTypes::TemporalWeeks;
70  }
71  else if ( !years && !months && !weeks && days && !hours && !minutes && !seconds )
72  {
73  mOriginalDuration = days;
74  mOriginalUnit = QgsUnitTypes::TemporalDays;
75  }
76  else if ( !years && !months && !weeks && !days && hours && !minutes && !seconds )
77  {
78  mOriginalDuration = hours;
79  mOriginalUnit = QgsUnitTypes::TemporalHours;
80  }
81  else if ( !years && !months && !weeks && !days && !hours && minutes && !seconds )
82  {
83  mOriginalDuration = minutes;
84  mOriginalUnit = QgsUnitTypes::TemporalMinutes;
85  }
86  else if ( !years && !months && !weeks && !days && !hours && !minutes && seconds )
87  {
88  mOriginalDuration = seconds;
89  mOriginalUnit = QgsUnitTypes::TemporalSeconds;
90  }
91  else if ( !years && !months && !weeks && !days && !hours && !minutes && !seconds )
92  {
93  mOriginalDuration = 0;
94  mOriginalUnit = QgsUnitTypes::TemporalSeconds;
95  }
96  else
97  {
98  mOriginalUnit = QgsUnitTypes::TemporalUnknownUnit;
99  }
100 }
101 
102 double QgsInterval::years() const
103 {
104  if ( mOriginalUnit == QgsUnitTypes::TemporalYears )
105  return mOriginalDuration;
106 
107  return mSeconds / YEARS;
108 }
109 
110 void QgsInterval::setYears( double years )
111 {
112  mSeconds = years * YEARS;
113  mValid = true;
114  mOriginalDuration = years;
115  mOriginalUnit = QgsUnitTypes::TemporalYears;
116 }
117 
118 double QgsInterval::months() const
119 {
120  if ( mOriginalUnit == QgsUnitTypes::TemporalMonths )
121  return mOriginalDuration;
122 
123  return mSeconds / MONTHS;
124 }
125 
126 void QgsInterval::setMonths( double months )
127 {
128  mSeconds = months * MONTHS;
129  mValid = true;
130  mOriginalDuration = months;
131  mOriginalUnit = QgsUnitTypes::TemporalMonths;
132 }
133 
134 double QgsInterval::weeks() const
135 {
136  if ( mOriginalUnit == QgsUnitTypes::TemporalWeeks )
137  return mOriginalDuration;
138 
139  return mSeconds / WEEKS;
140 }
141 
142 
143 void QgsInterval::setWeeks( double weeks )
144 {
145  mSeconds = weeks * WEEKS;
146  mValid = true;
147  mOriginalDuration = weeks;
148  mOriginalUnit = QgsUnitTypes::TemporalWeeks;
149 }
150 
151 double QgsInterval::days() const
152 {
153  if ( mOriginalUnit == QgsUnitTypes::TemporalDays )
154  return mOriginalDuration;
155 
156  return mSeconds / DAY;
157 }
158 
159 
160 void QgsInterval::setDays( double days )
161 {
162  mSeconds = days * DAY;
163  mValid = true;
164  mOriginalDuration = days;
165  mOriginalUnit = QgsUnitTypes::TemporalDays;
166 }
167 
168 double QgsInterval::hours() const
169 {
170  if ( mOriginalUnit == QgsUnitTypes::TemporalHours )
171  return mOriginalDuration;
172 
173  return mSeconds / HOUR;
174 }
175 
176 
177 void QgsInterval::setHours( double hours )
178 {
179  mSeconds = hours * HOUR;
180  mValid = true;
181  mOriginalDuration = hours;
182  mOriginalUnit = QgsUnitTypes::TemporalHours;
183 }
184 
185 double QgsInterval::minutes() const
186 {
187  if ( mOriginalUnit == QgsUnitTypes::TemporalMinutes )
188  return mOriginalDuration;
189 
190  return mSeconds / MINUTE;
191 }
192 
193 void QgsInterval::setMinutes( double minutes )
194 {
195  mSeconds = minutes * MINUTE;
196  mValid = true;
197  mOriginalDuration = minutes;
198  mOriginalUnit = QgsUnitTypes::TemporalMinutes;
199 }
200 
201 void QgsInterval::setSeconds( double seconds )
202 {
203  mSeconds = seconds;
204  mValid = true;
205  mOriginalDuration = seconds;
206  mOriginalUnit = QgsUnitTypes::TemporalSeconds;
207 }
208 
209 QgsInterval QgsInterval::fromString( const QString &string )
210 {
211  double seconds = 0;
212  QRegExp rx( "([-+]?\\d*\\.?\\d+\\s+\\S+)", Qt::CaseInsensitive );
213  QStringList list;
214  int pos = 0;
215 
216  while ( ( pos = rx.indexIn( string, pos ) ) != -1 )
217  {
218  list << rx.cap( 1 );
219  pos += rx.matchedLength();
220  }
221 
222  QMap<int, QStringList> map;
223  map.insert( 1, QStringList() << QStringLiteral( "second" ) << QStringLiteral( "seconds" ) << QObject::tr( "second|seconds", "list of words separated by | which reference years" ).split( '|' ) );
224  map.insert( 0 + MINUTE, QStringList() << QStringLiteral( "minute" ) << QStringLiteral( "minutes" ) << QObject::tr( "minute|minutes", "list of words separated by | which reference minutes" ).split( '|' ) );
225  map.insert( 0 + HOUR, QStringList() << QStringLiteral( "hour" ) << QStringLiteral( "hours" ) << QObject::tr( "hour|hours", "list of words separated by | which reference minutes hours" ).split( '|' ) );
226  map.insert( 0 + DAY, QStringList() << QStringLiteral( "day" ) << QStringLiteral( "days" ) << QObject::tr( "day|days", "list of words separated by | which reference days" ).split( '|' ) );
227  map.insert( 0 + WEEKS, QStringList() << QStringLiteral( "week" ) << QStringLiteral( "weeks" ) << QObject::tr( "week|weeks", "wordlist separated by | which reference weeks" ).split( '|' ) );
228  map.insert( 0 + MONTHS, QStringList() << QStringLiteral( "month" ) << QStringLiteral( "months" ) << QObject::tr( "month|months", "list of words separated by | which reference months" ).split( '|' ) );
229  map.insert( 0 + YEARS, QStringList() << QStringLiteral( "year" ) << QStringLiteral( "years" ) << QObject::tr( "year|years", "list of words separated by | which reference years" ).split( '|' ) );
230 
231  const auto constList = list;
232  for ( const QString &match : constList )
233  {
234  QStringList split = match.split( QRegExp( "\\s+" ) );
235  bool ok;
236  double value = split.at( 0 ).toDouble( &ok );
237  if ( !ok )
238  {
239  continue;
240  }
241 
242  bool matched = false;
243  QMap<int, QStringList>::const_iterator it = map.constBegin();
244  for ( ; it != map.constEnd(); ++it )
245  {
246  int duration = it.key();
247  const auto constValue = it.value();
248  for ( const QString &name : constValue )
249  {
250  if ( match.contains( name, Qt::CaseInsensitive ) )
251  {
252  matched = true;
253  break;
254  }
255  }
256 
257  if ( matched )
258  {
259  seconds += value * duration;
260  break;
261  }
262  }
263  }
264 
265  // If we can't parse the string at all then we just return invalid
266  if ( seconds == 0 )
267  return QgsInterval();
268 
269  return QgsInterval( seconds );
270 }
271 
272 QDebug operator<<( QDebug dbg, const QgsInterval &interval )
273 {
274  if ( !interval.isValid() )
275  dbg.nospace() << "QgsInterval()";
276  else
277  dbg.nospace() << "QgsInterval(" << interval.seconds() << ")";
278  return dbg.maybeSpace();
279 }
280 
281 QgsInterval operator-( const QDateTime &dt1, const QDateTime &dt2 )
282 {
283  qint64 mSeconds = dt2.msecsTo( dt1 );
284  return QgsInterval( mSeconds / 1000.0 );
285 }
286 
287 QDateTime operator+( const QDateTime &start, const QgsInterval &interval )
288 {
289  return start.addMSecs( static_cast<qint64>( interval.seconds() * 1000.0 ) );
290 }
291 
292 QgsInterval operator-( QDate date1, QDate date2 )
293 {
294  qint64 seconds = static_cast< qint64 >( date2.daysTo( date1 ) ) * 24 * 60 * 60;
295  return QgsInterval( seconds );
296 }
297 
298 QgsInterval operator-( QTime time1, QTime time2 )
299 {
300  qint64 mSeconds = time2.msecsTo( time1 );
301  return QgsInterval( mSeconds / 1000.0 );
302 }
A representation of the interval between two datetime values.
Definition: qgsinterval.h:42
static const int MINUTE
Seconds per minute.
Definition: qgsinterval.h:58
bool isValid() const
Returns true if the interval is valid.
Definition: qgsinterval.h:255
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:50
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.
Definition: qgsinterval.h:236
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:56
static const int WEEKS
Seconds per week.
Definition: qgsinterval.h:52
static const int DAY
Seconds per day.
Definition: qgsinterval.h:54
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:48
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.
Definition: qgsunittypes.h:39
TemporalUnit
Temporal units.
Definition: qgsunittypes.h:150
@ TemporalMonths
Months.
Definition: qgsunittypes.h:157
@ TemporalUnknownUnit
Unknown time unit.
Definition: qgsunittypes.h:162
@ TemporalWeeks
Weeks.
Definition: qgsunittypes.h:156
@ TemporalDays
Days.
Definition: qgsunittypes.h:155
@ TemporalSeconds
Seconds.
Definition: qgsunittypes.h:152
@ TemporalMinutes
Minutes.
Definition: qgsunittypes.h:153
@ TemporalYears
Years.
Definition: qgsunittypes.h:158
@ TemporalHours
Hours.
Definition: qgsunittypes.h:154
QDebug operator<<(QDebug dbg, const QgsInterval &interval)
Debug string representation of interval.
QgsInterval operator-(const QDateTime &dt1, const QDateTime &dt2)
Returns the interval between two datetimes.
QDateTime operator+(const QDateTime &start, const QgsInterval &interval)
Adds an interval to a datetime.