Skip to content

Commit

Permalink
[FEATURE][expressions] Expanded support for date/time calcs
Browse files Browse the repository at this point in the history
Adds support for date - date, time - time and datetime - datetime
type calculations which return an interval.
  • Loading branch information
nyalldawson committed May 24, 2016
1 parent db0db36 commit 8ddcf76
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 11 deletions.
33 changes: 26 additions & 7 deletions src/core/qgsexpression.cpp
Expand Up @@ -4051,21 +4051,40 @@ QVariant QgsExpression::NodeBinaryOperator::eval( QgsExpression *parent, const Q
}
return QVariant( computeDateTimeFromInterval( dL, &iL ) );
}
else if (( vL.type() == QVariant::Date && vR.type() == QVariant::Time ) ||
( vR.type() == QVariant::Date && vL.type() == QVariant::Time ) )
else if ( mOp == boPlus && (( vL.type() == QVariant::Date && vR.type() == QVariant::Time ) ||
( vR.type() == QVariant::Date && vL.type() == QVariant::Time ) ) )
{
QDate date = getDateValue( vL.type() == QVariant::Date ? vL : vR, parent );
ENSURE_NO_EVAL_ERROR;
QTime time = getTimeValue( vR.type() == QVariant::Time ? vR : vL, parent );
ENSURE_NO_EVAL_ERROR;
if ( mOp == boMinus || mOp == boDiv || mOp == boMul || mOp == boMod )
{
parent->setEvalErrorString( tr( "Can't preform -, /, *, or % on Date and Time" ) );
return QVariant();
}
QDateTime dt = QDateTime( date, time );
return QVariant( dt );
}
else if ( mOp == boMinus && vL.type() == QVariant::Date && vR.type() == QVariant::Date )
{
QDate date1 = getDateValue( vL, parent );
ENSURE_NO_EVAL_ERROR;
QDate date2 = getDateValue( vR, parent );
ENSURE_NO_EVAL_ERROR;
return date1 - date2;
}
else if ( mOp == boMinus && vL.type() == QVariant::Time && vR.type() == QVariant::Time )
{
QTime time1 = getTimeValue( vL, parent );
ENSURE_NO_EVAL_ERROR;
QTime time2 = getTimeValue( vR, parent );
ENSURE_NO_EVAL_ERROR;
return time1 - time2;
}
else if ( mOp == boMinus && vL.type() == QVariant::DateTime && vR.type() == QVariant::DateTime )
{
QDateTime datetime1 = getDateTimeValue( vL, parent );
ENSURE_NO_EVAL_ERROR;
QDateTime datetime2 = getDateTimeValue( vR, parent );
ENSURE_NO_EVAL_ERROR;
return datetime1 - datetime2;
}
else
{
// general floating point arithmetic
Expand Down
12 changes: 12 additions & 0 deletions src/core/qgsinterval.cpp
Expand Up @@ -129,3 +129,15 @@ QDateTime operator+( const QDateTime& start, const QgsInterval& interval )
{
return start.addMSecs( static_cast<qint64>( interval.seconds() * 1000.0 ) );
}

QgsInterval operator-( const QDate& date1, const QDate& date2 )
{
qint64 seconds = date2.daysTo( date1 ) * 24 * 60 * 60;
return QgsInterval( seconds );
}

QgsInterval operator-( const QTime& time1, const QTime& time2 )
{
qint64 mSeconds = time2.msecsTo( time1 );
return QgsInterval( mSeconds / 1000.0 );
}
24 changes: 20 additions & 4 deletions src/core/qgsinterval.h
Expand Up @@ -172,13 +172,29 @@ class CORE_EXPORT QgsInterval

Q_DECLARE_METATYPE( QgsInterval )

/** Returns the interval between two datetimes
* @param dt1 start datetime
* @param dt2 datetime to subtract, ie subtract dt2 from dt1
/** Returns the interval between two datetimes.
* @param datetime1 start datetime
* @param datetime2 datetime to subtract, ie subtract datetime2 from datetime1
* @note added in QGIS 2.16
* @note not available in Python bindings
*/
QgsInterval CORE_EXPORT operator-( const QDateTime& dt1, const QDateTime& dt2 );
QgsInterval CORE_EXPORT operator-( const QDateTime& datetime1, const QDateTime& datetime2 );

/** Returns the interval between two dates.
* @param date1 start date
* @param date2 date to subtract, ie subtract date2 from date1
* @note added in QGIS 2.16
* @note not available in Python bindings
*/
QgsInterval CORE_EXPORT operator-( const QDate& date1, const QDate& date2 );

/** Returns the interval between two times.
* @param time1 start time
* @param time2 time to subtract, ie subtract time2 from time1
* @note added in QGIS 2.16
* @note not available in Python bindings
*/
QgsInterval CORE_EXPORT operator-( const QTime& time1, const QTime& time2 );

/** Adds an interval to a datetime
* @param start initial datetime
Expand Down
3 changes: 3 additions & 0 deletions tests/src/core/testqgsexpression.cpp
Expand Up @@ -834,6 +834,9 @@ class TestQgsExpression: public QObject
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 );
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 ) ) );
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 ) ) );
QTest::newRow( "date - date" ) << "to_date('2013-03-04') - to_date('2013-03-01')" << false << QVariant( QgsInterval( 3*24*60*60 ) );
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 ) );
QTest::newRow( "time - time" ) << "to_time('08:30:00') - to_time('05:15:00')" << false << QVariant( QgsInterval( 3 * 60*60 + 15*60 ) );

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

0 comments on commit 8ddcf76

Please sign in to comment.