Skip to content

Commit

Permalink
[feature][expressions] New expression function "make_interval"
Browse files Browse the repository at this point in the history
Allows direct construction of interval values from years/months/weeks/
days/hours/minutes/second values, without having to construct
a string representation of the interval first
  • Loading branch information
nyalldawson committed May 9, 2020
1 parent ca64c6c commit da042bb
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 0 deletions.
18 changes: 18 additions & 0 deletions resources/function_help/json/make_interval
@@ -0,0 +1,18 @@
{
"name": "make_interval",
"type": "function",
"description": "Creates an interval value from year, month, weeks, days, hours, minute and seconds values.",
"arguments": [
{"arg":"years","description":"Number of years (assumes a 365.25 day year length).", "optional": true, "default": "0"},
{"arg":"months","description":"Number of months (assumes a 30 day month length)", "optional": true, "default": "0"},
{"arg":"weeks","description":"Number of weeks", "optional": true, "default": "0"},
{"arg":"days","description":"Number of days", "optional": true, "default": "0"},
{"arg":"hours","description":"Number of hours", "optional": true, "default": "0"},
{"arg":"minutes","description":"Number of minutes", "optional": true, "default": "0"},
{"arg":"seconds","description":"Number of seconds", "optional": true, "default": "0"}
],
"examples": [
{ "expression":"make_interval(hours:=3)", "returns":"3 hour interval"},
{ "expression":"make_interval(days:=2, hours:=3)", "returns":"2 day, 3 hour interval"}
]
}
21 changes: 21 additions & 0 deletions src/core/expression/qgsexpressionfunction.cpp
Expand Up @@ -1157,6 +1157,19 @@ static QVariant fcnMakeDateTime( const QVariantList &values, const QgsExpression
return QVariant( QDateTime( date, time ) );
}

static QVariant fcnMakeInterval( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
const int years = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
const int months = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
const int weeks = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
const int days = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
const int hours = QgsExpressionUtils::getIntValue( values.at( 4 ), parent );
const int minutes = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 6 ), parent );

return QVariant::fromValue( QgsInterval( years, months, weeks, days, hours, minutes, seconds ) );
}

static QVariant fcnCoalesce( const QVariantList &values, const QgsExpressionContext *, QgsExpression *, const QgsExpressionNodeFunction * )
{
for ( const QVariant &value : values )
Expand Down Expand Up @@ -5807,6 +5820,14 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
<< QgsExpressionFunction::Parameter( QStringLiteral( "minute" ) )
<< QgsExpressionFunction::Parameter( QStringLiteral( "second" ) ),
fcnMakeDateTime, QStringLiteral( "Date and Time" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "make_interval" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "years" ), true, 0 )
<< QgsExpressionFunction::Parameter( QStringLiteral( "months" ), true, 0 )
<< QgsExpressionFunction::Parameter( QStringLiteral( "weeks" ), true, 0 )
<< QgsExpressionFunction::Parameter( QStringLiteral( "days" ), true, 0 )
<< QgsExpressionFunction::Parameter( QStringLiteral( "hours" ), true, 0 )
<< QgsExpressionFunction::Parameter( QStringLiteral( "minutes" ), true, 0 )
<< QgsExpressionFunction::Parameter( QStringLiteral( "seconds" ), true, 0 ),
fcnMakeInterval, QStringLiteral( "Date and Time" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "lower" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "string" ) ), fcnLower, QStringLiteral( "String" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "upper" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "string" ) ), fcnUpper, QStringLiteral( "String" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "title" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "string" ) ), fcnTitle, QStringLiteral( "String" ) )
Expand Down
8 changes: 8 additions & 0 deletions tests/src/core/testqgsexpression.cpp
Expand Up @@ -1369,6 +1369,14 @@ class TestQgsExpression: public QObject
QTest::newRow( "make datetime with ms" ) << "make_datetime(2012,7,8,13,6,28.5)" << false << QVariant( QDateTime( QDate( 2012, 7, 8 ), QTime( 13, 6, 28, 500 ) ) );
QTest::newRow( "make datetime invalid" ) << "make_datetime(2012,7,8,'a',6,28)" << true << QVariant();
QTest::newRow( "make datetime invalid 2" ) << "make_datetime(2012,7,8,2012,16,28)" << true << QVariant();
QTest::newRow( "make interval years" ) << "second(make_interval(years:=2))" << false << QVariant( 63115200.0 );
QTest::newRow( "make interval months" ) << "second(make_interval(months:=2))" << false << QVariant( 5184000.0 );
QTest::newRow( "make interval weeks" ) << "second(make_interval(weeks:=2))" << false << QVariant( 1209600.0 );
QTest::newRow( "make interval days" ) << "second(make_interval(days:=2))" << false << QVariant( 172800.0 );
QTest::newRow( "make interval hours" ) << "second(make_interval(hours:=2))" << false << QVariant( 7200.0 );
QTest::newRow( "make interval minutes" ) << "second(make_interval(minutes:=2))" << false << QVariant( 120.0 );
QTest::newRow( "make interval seconds" ) << "second(make_interval(seconds:=2))" << false << QVariant( 2.0 );
QTest::newRow( "make interval mixed" ) << "second(make_interval(2,3,4,5,6,7,8))" << false << QVariant( 73764428.0 );
QTest::newRow( "to date" ) << "todate('2012-06-28')" << false << QVariant( QDate( 2012, 6, 28 ) );
QTest::newRow( "to interval" ) << "tointerval('1 Year 1 Month 1 Week 1 Hour 1 Minute')" << false << QVariant::fromValue( QgsInterval( 34758060 ) );
QTest::newRow( "day with date" ) << "day('2012-06-28')" << false << QVariant( 28 );
Expand Down

0 comments on commit da042bb

Please sign in to comment.