QGIS API Documentation  3.8.0-Zanzibar (11aff65)
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 "qgis.h"
18 #include <QString>
19 #include <QStringList>
20 #include <QMap>
21 #include <QObject>
22 #include <QDebug>
23 #include <QDateTime>
24 
25 /***************************************************************************
26  * This class is considered CRITICAL and any change MUST be accompanied with
27  * full unit tests in test_qgsinterval.py.
28  * See details in QEP #17
29  ****************************************************************************/
30 
31 QgsInterval::QgsInterval( double seconds )
32  : mSeconds( seconds )
33  , mValid( true )
34 { }
35 
37 {
38  if ( !mValid && !other.mValid )
39  return true;
40  else if ( mValid && other.mValid )
41  return qgsDoubleNear( mSeconds, other.mSeconds );
42  else
43  return false;
44 }
45 
46 QgsInterval QgsInterval::fromString( const QString &string )
47 {
48  double seconds = 0;
49  QRegExp rx( "([-+]?\\d*\\.?\\d+\\s+\\S+)", Qt::CaseInsensitive );
50  QStringList list;
51  int pos = 0;
52 
53  while ( ( pos = rx.indexIn( string, pos ) ) != -1 )
54  {
55  list << rx.cap( 1 );
56  pos += rx.matchedLength();
57  }
58 
59  QMap<int, QStringList> map;
60  map.insert( 1, QStringList() << QStringLiteral( "second" ) << QStringLiteral( "seconds" ) << QObject::tr( "second|seconds", "list of words separated by | which reference years" ).split( '|' ) );
61  map.insert( 0 + MINUTE, QStringList() << QStringLiteral( "minute" ) << QStringLiteral( "minutes" ) << QObject::tr( "minute|minutes", "list of words separated by | which reference minutes" ).split( '|' ) );
62  map.insert( 0 + HOUR, QStringList() << QStringLiteral( "hour" ) << QStringLiteral( "hours" ) << QObject::tr( "hour|hours", "list of words separated by | which reference minutes hours" ).split( '|' ) );
63  map.insert( 0 + DAY, QStringList() << QStringLiteral( "day" ) << QStringLiteral( "days" ) << QObject::tr( "day|days", "list of words separated by | which reference days" ).split( '|' ) );
64  map.insert( 0 + WEEKS, QStringList() << QStringLiteral( "week" ) << QStringLiteral( "weeks" ) << QObject::tr( "week|weeks", "wordlist separated by | which reference weeks" ).split( '|' ) );
65  map.insert( 0 + MONTHS, QStringList() << QStringLiteral( "month" ) << QStringLiteral( "months" ) << QObject::tr( "month|months", "list of words separated by | which reference months" ).split( '|' ) );
66  map.insert( 0 + YEARS, QStringList() << QStringLiteral( "year" ) << QStringLiteral( "years" ) << QObject::tr( "year|years", "list of words separated by | which reference years" ).split( '|' ) );
67 
68  const auto constList = list;
69  for ( const QString &match : constList )
70  {
71  QStringList split = match.split( QRegExp( "\\s+" ) );
72  bool ok;
73  double value = split.at( 0 ).toDouble( &ok );
74  if ( !ok )
75  {
76  continue;
77  }
78 
79  bool matched = false;
80  QMap<int, QStringList>::const_iterator it = map.constBegin();
81  for ( ; it != map.constEnd(); ++it )
82  {
83  int duration = it.key();
84  const auto constValue = it.value();
85  for ( const QString &name : constValue )
86  {
87  if ( match.contains( name, Qt::CaseInsensitive ) )
88  {
89  matched = true;
90  break;
91  }
92  }
93 
94  if ( matched )
95  {
96  seconds += value * duration;
97  break;
98  }
99  }
100  }
101 
102  // If we can't parse the string at all then we just return invalid
103  if ( seconds == 0 )
104  return QgsInterval();
105 
106  return QgsInterval( seconds );
107 }
108 
109 QDebug operator<<( QDebug dbg, const QgsInterval &interval )
110 {
111  if ( !interval.isValid() )
112  dbg.nospace() << "QgsInterval()";
113  else
114  dbg.nospace() << "QgsInterval(" << interval.seconds() << ")";
115  return dbg.maybeSpace();
116 }
117 
118 QgsInterval operator-( const QDateTime &dt1, const QDateTime &dt2 )
119 {
120  qint64 mSeconds = dt2.msecsTo( dt1 );
121  return QgsInterval( mSeconds / 1000.0 );
122 }
123 
124 QDateTime operator+( const QDateTime &start, QgsInterval interval )
125 {
126  return start.addMSecs( static_cast<qint64>( interval.seconds() * 1000.0 ) );
127 }
128 
129 QgsInterval operator-( QDate date1, QDate date2 )
130 {
131  qint64 seconds = static_cast< qint64 >( date2.daysTo( date1 ) ) * 24 * 60 * 60;
132  return QgsInterval( seconds );
133 }
134 
135 QgsInterval operator-( QTime time1, QTime time2 )
136 {
137  qint64 mSeconds = time2.msecsTo( time1 );
138  return QgsInterval( mSeconds / 1000.0 );
139 }
static const int YEARS
Seconds per year (average)
Definition: qgsinterval.h:46
bool operator==(QgsInterval other) const
Definition: qgsinterval.cpp:36
bool isValid() const
Returns true if the interval is valid.
Definition: qgsinterval.h:164
static const int MONTHS
Seconds per month, based on 30 day month.
Definition: qgsinterval.h:48
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:265
double seconds() const
Returns the interval duration in seconds.
Definition: qgsinterval.h:151
static QgsInterval fromString(const QString &string)
Converts a string to an interval.
Definition: qgsinterval.cpp:46
static const int HOUR
Seconds per hour.
Definition: qgsinterval.h:54
static const int WEEKS
Seconds per week.
Definition: qgsinterval.h:50
QDateTime operator+(const QDateTime &start, QgsInterval interval)
static const int DAY
Seconds per day.
Definition: qgsinterval.h:52
QgsInterval operator-(const QDateTime &dt1, const QDateTime &dt2)
Returns the interval between two datetimes.
QDebug operator<<(QDebug dbg, const QgsInterval &interval)
Debug string representation of interval.
A representation of the interval between two datetime values.
Definition: qgsinterval.h:39
static const int MINUTE
Seconds per minute.
Definition: qgsinterval.h:56
QgsInterval()=default
Default constructor for QgsInterval.