Skip to content

Commit 8ddcf76

Browse files
committed
[FEATURE][expressions] Expanded support for date/time calcs
Adds support for date - date, time - time and datetime - datetime type calculations which return an interval.
1 parent db0db36 commit 8ddcf76

File tree

4 files changed

+61
-11
lines changed

4 files changed

+61
-11
lines changed

src/core/qgsexpression.cpp

+26-7
Original file line numberDiff line numberDiff line change
@@ -4051,21 +4051,40 @@ QVariant QgsExpression::NodeBinaryOperator::eval( QgsExpression *parent, const Q
40514051
}
40524052
return QVariant( computeDateTimeFromInterval( dL, &iL ) );
40534053
}
4054-
else if (( vL.type() == QVariant::Date && vR.type() == QVariant::Time ) ||
4055-
( vR.type() == QVariant::Date && vL.type() == QVariant::Time ) )
4054+
else if ( mOp == boPlus && (( vL.type() == QVariant::Date && vR.type() == QVariant::Time ) ||
4055+
( vR.type() == QVariant::Date && vL.type() == QVariant::Time ) ) )
40564056
{
40574057
QDate date = getDateValue( vL.type() == QVariant::Date ? vL : vR, parent );
40584058
ENSURE_NO_EVAL_ERROR;
40594059
QTime time = getTimeValue( vR.type() == QVariant::Time ? vR : vL, parent );
40604060
ENSURE_NO_EVAL_ERROR;
4061-
if ( mOp == boMinus || mOp == boDiv || mOp == boMul || mOp == boMod )
4062-
{
4063-
parent->setEvalErrorString( tr( "Can't preform -, /, *, or % on Date and Time" ) );
4064-
return QVariant();
4065-
}
40664061
QDateTime dt = QDateTime( date, time );
40674062
return QVariant( dt );
40684063
}
4064+
else if ( mOp == boMinus && vL.type() == QVariant::Date && vR.type() == QVariant::Date )
4065+
{
4066+
QDate date1 = getDateValue( vL, parent );
4067+
ENSURE_NO_EVAL_ERROR;
4068+
QDate date2 = getDateValue( vR, parent );
4069+
ENSURE_NO_EVAL_ERROR;
4070+
return date1 - date2;
4071+
}
4072+
else if ( mOp == boMinus && vL.type() == QVariant::Time && vR.type() == QVariant::Time )
4073+
{
4074+
QTime time1 = getTimeValue( vL, parent );
4075+
ENSURE_NO_EVAL_ERROR;
4076+
QTime time2 = getTimeValue( vR, parent );
4077+
ENSURE_NO_EVAL_ERROR;
4078+
return time1 - time2;
4079+
}
4080+
else if ( mOp == boMinus && vL.type() == QVariant::DateTime && vR.type() == QVariant::DateTime )
4081+
{
4082+
QDateTime datetime1 = getDateTimeValue( vL, parent );
4083+
ENSURE_NO_EVAL_ERROR;
4084+
QDateTime datetime2 = getDateTimeValue( vR, parent );
4085+
ENSURE_NO_EVAL_ERROR;
4086+
return datetime1 - datetime2;
4087+
}
40694088
else
40704089
{
40714090
// general floating point arithmetic

src/core/qgsinterval.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,15 @@ QDateTime operator+( const QDateTime& start, const QgsInterval& interval )
129129
{
130130
return start.addMSecs( static_cast<qint64>( interval.seconds() * 1000.0 ) );
131131
}
132+
133+
QgsInterval operator-( const QDate& date1, const QDate& date2 )
134+
{
135+
qint64 seconds = date2.daysTo( date1 ) * 24 * 60 * 60;
136+
return QgsInterval( seconds );
137+
}
138+
139+
QgsInterval operator-( const QTime& time1, const QTime& time2 )
140+
{
141+
qint64 mSeconds = time2.msecsTo( time1 );
142+
return QgsInterval( mSeconds / 1000.0 );
143+
}

src/core/qgsinterval.h

+20-4
Original file line numberDiff line numberDiff line change
@@ -172,13 +172,29 @@ class CORE_EXPORT QgsInterval
172172

173173
Q_DECLARE_METATYPE( QgsInterval )
174174

175-
/** Returns the interval between two datetimes
176-
* @param dt1 start datetime
177-
* @param dt2 datetime to subtract, ie subtract dt2 from dt1
175+
/** Returns the interval between two datetimes.
176+
* @param datetime1 start datetime
177+
* @param datetime2 datetime to subtract, ie subtract datetime2 from datetime1
178178
* @note added in QGIS 2.16
179179
* @note not available in Python bindings
180180
*/
181-
QgsInterval CORE_EXPORT operator-( const QDateTime& dt1, const QDateTime& dt2 );
181+
QgsInterval CORE_EXPORT operator-( const QDateTime& datetime1, const QDateTime& datetime2 );
182+
183+
/** Returns the interval between two dates.
184+
* @param date1 start date
185+
* @param date2 date to subtract, ie subtract date2 from date1
186+
* @note added in QGIS 2.16
187+
* @note not available in Python bindings
188+
*/
189+
QgsInterval CORE_EXPORT operator-( const QDate& date1, const QDate& date2 );
190+
191+
/** Returns the interval between two times.
192+
* @param time1 start time
193+
* @param time2 time to subtract, ie subtract time2 from time1
194+
* @note added in QGIS 2.16
195+
* @note not available in Python bindings
196+
*/
197+
QgsInterval CORE_EXPORT operator-( const QTime& time1, const QTime& time2 );
182198

183199
/** Adds an interval to a datetime
184200
* @param start initial datetime

tests/src/core/testqgsexpression.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,9 @@ class TestQgsExpression: public QObject
834834
QTest::newRow( "age datetime" ) << "hour(age(to_datetime('2004-03-22 08:30:22'),to_datetime('2004-03-12 07:30:22')))" << false << QVariant( 241.0 );
835835
QTest::newRow( "date + time" ) << "to_date('2013-03-04') + to_time('13:14:15')" << false << QVariant( QDateTime( QDate( 2013, 3, 4 ), QTime( 13, 14, 15 ) ) );
836836
QTest::newRow( "time + date" ) << "to_time('13:14:15') + to_date('2013-03-04')" << false << QVariant( QDateTime( QDate( 2013, 3, 4 ), QTime( 13, 14, 15 ) ) );
837+
QTest::newRow( "date - date" ) << "to_date('2013-03-04') - to_date('2013-03-01')" << false << QVariant( QgsInterval( 3*24*60*60 ) );
838+
QTest::newRow( "datetime - datetime" ) << "to_datetime('2013-03-04 08:30:00') - to_datetime('2013-03-01 05:15:00')" << false << QVariant( QgsInterval( 3*24*60*60 + 3 * 60*60 + 15*60 ) );
839+
QTest::newRow( "time - time" ) << "to_time('08:30:00') - to_time('05:15:00')" << false << QVariant( QgsInterval( 3 * 60*60 + 15*60 ) );
837840

838841
// Color functions
839842
QTest::newRow( "ramp color" ) << "ramp_color('Spectral',0.3)" << false << QVariant( "254,190,116,255" );

0 commit comments

Comments
 (0)