mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
Add expression functions for handling date/time:
- year,month,day,hour,minute,second extraction - new QgsInterval objects - handles time amounts - age() function returns the difference between two datetimes - $now returns the current date and time - support for datetime - interval = new datetime - tointerval, todate, totime functions - tests ;)
This commit is contained in:
parent
4b81e3601c
commit
c467e79f3c
@ -1,4 +1,3 @@
|
||||
|
||||
class QgsExpression
|
||||
{
|
||||
%TypeHeaderCode
|
||||
@ -304,7 +303,24 @@ public:
|
||||
virtual void visit( QgsExpression::NodeCondition* n ) = 0;
|
||||
};
|
||||
|
||||
class Interval
|
||||
{
|
||||
public:
|
||||
Interval(int seconds);
|
||||
~Interval();
|
||||
int years();
|
||||
int weeks();
|
||||
int days();
|
||||
int hours();
|
||||
int minutes();
|
||||
int seconds();
|
||||
bool isValid();
|
||||
void setValid(bool valid);
|
||||
bool operator==(const QgsExpression::Interval& other) const;
|
||||
static QgsExpression::Interval invalidInterVal();
|
||||
static QgsExpression::Interval fromString(QString string);
|
||||
};
|
||||
|
||||
/** entry function for the visitor pattern */
|
||||
void acceptVisitor( QgsExpression::Visitor& v );
|
||||
|
||||
};
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include <QtDebug>
|
||||
#include <QDomDocument>
|
||||
#include <QSettings>
|
||||
#include <QDate>
|
||||
#include <QRegExp>
|
||||
|
||||
#include <math.h>
|
||||
#include <limits>
|
||||
@ -30,6 +32,79 @@
|
||||
// from parser
|
||||
extern QgsExpression::Node* parseExpression( const QString& str, QString& parserErrorMsg );
|
||||
|
||||
QgsExpression::Interval::~Interval() {}
|
||||
|
||||
QgsExpression::Interval QgsExpression::Interval::invalidInterVal()
|
||||
{
|
||||
QgsExpression::Interval inter = QgsExpression::Interval();
|
||||
inter.setValid( false );
|
||||
return inter;
|
||||
}
|
||||
|
||||
QgsExpression::Interval QgsExpression::Interval::fromString( QString string )
|
||||
{
|
||||
int seconds = 0;
|
||||
QRegExp rx( "(\\d?\\.?\\d+\\s+[a-z]+)", Qt::CaseInsensitive );
|
||||
QStringList list;
|
||||
int pos = 0;
|
||||
|
||||
while (( pos = rx.indexIn( string, pos ) ) != -1 )
|
||||
{
|
||||
list << rx.cap( 1 );
|
||||
pos += rx.matchedLength();
|
||||
}
|
||||
|
||||
foreach( QString match, list )
|
||||
{
|
||||
QStringList split = match.split( QRegExp( "\\s+" ) );
|
||||
bool ok;
|
||||
int value = split.at( 0 ).toInt( &ok );
|
||||
if ( !ok )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( match.contains( "day", Qt::CaseInsensitive ) ||
|
||||
match.contains( QObject::tr("day", "Note: Word is part matched in code"), Qt::CaseInsensitive )||
|
||||
match.contains( QObject::tr("days", "Note: Word is part matched in code"), Qt::CaseInsensitive) )
|
||||
seconds += value * QgsExpression::Interval::DAY;
|
||||
if ( match.contains( "week", Qt::CaseInsensitive ) ||
|
||||
match.contains( QObject::tr("week", "Note: Word is part matched in code"), Qt::CaseInsensitive ) ||
|
||||
match.contains( QObject::tr("weeks", "Note: Word is part matched in code"), Qt::CaseInsensitive ) )
|
||||
seconds += value * QgsExpression::Interval::WEEKS;
|
||||
if ( match.contains( "month", Qt::CaseInsensitive ) ||
|
||||
match.contains( QObject::tr("month", "Note: Word is part matched in code"), Qt::CaseInsensitive ) ||
|
||||
match.contains( QObject::tr("months", "Note: Word is part matched in code"), Qt::CaseInsensitive ) )
|
||||
seconds += value * QgsExpression::Interval::MONTHS;
|
||||
if ( match.contains( "year", Qt::CaseInsensitive ) ||
|
||||
match.contains( QObject::tr("year", "Note: Word is part matched in code"), Qt::CaseInsensitive ) ||
|
||||
match.contains( QObject::tr("years", "Note: Word is part matched in code"), Qt::CaseInsensitive ) )
|
||||
seconds += value * QgsExpression::Interval::YEARS;
|
||||
if ( match.contains( "second", Qt::CaseInsensitive ) ||
|
||||
match.contains( QObject::tr("second", "Note: Word is part matched in code"), Qt::CaseInsensitive ) ||
|
||||
match.contains( QObject::tr("seconds", "Note: Word is part matched in code"), Qt::CaseInsensitive ) )
|
||||
seconds += value;
|
||||
if ( match.contains( "minute", Qt::CaseInsensitive ) ||
|
||||
match.contains( QObject::tr("minute", "Note: Word is part matched in code"), Qt::CaseInsensitive ) ||
|
||||
match.contains( QObject::tr("minutes", "Note: Word is part matched in code"), Qt::CaseInsensitive ) )
|
||||
seconds += value * QgsExpression::Interval::MINUTE;
|
||||
if ( match.contains( "hour", Qt::CaseInsensitive ) ||
|
||||
match.contains( QObject::tr("hour", "Note: Word is part matched in code"), Qt::CaseInsensitive ) ||
|
||||
match.contains( QObject::tr("hours", "Note: Word is part matched in code"), Qt::CaseInsensitive ) )
|
||||
seconds += value * QgsExpression::Interval::HOUR;
|
||||
}
|
||||
|
||||
// If we can't parse the string at all then we just return invalid
|
||||
if ( seconds == 0 )
|
||||
return QgsExpression::Interval::invalidInterVal();
|
||||
|
||||
return QgsExpression::Interval( seconds );
|
||||
}
|
||||
|
||||
bool QgsExpression::Interval::operator==( const QgsExpression::Interval& other ) const
|
||||
{
|
||||
return ( mSeconds == other.mSeconds );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// three-value logic
|
||||
@ -91,6 +166,26 @@ inline bool isDoubleSafe( const QVariant& v )
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool isDateTimeSafe( const QVariant& v )
|
||||
{
|
||||
return v.type() == QVariant::DateTime || v.type() == QVariant::Date ||
|
||||
v.type() == QVariant::Time;
|
||||
}
|
||||
|
||||
inline bool isIntervalSafe( const QVariant& v )
|
||||
{
|
||||
if ( v.canConvert<QgsExpression::Interval>() )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( v.type() == QVariant::String )
|
||||
{
|
||||
return QgsExpression::Interval::fromString( v.toString() ).isValid();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool isNull( const QVariant& v ) { return v.isNull(); }
|
||||
|
||||
///////////////////////////////////////////////
|
||||
@ -167,6 +262,65 @@ static int getIntValue( const QVariant& value, QgsExpression* parent )
|
||||
}
|
||||
}
|
||||
|
||||
static QDateTime getDateTimeValue( const QVariant& value, QgsExpression* parent )
|
||||
{
|
||||
QDateTime d = value.toDateTime();
|
||||
if ( d.isValid() )
|
||||
{
|
||||
return d;
|
||||
}
|
||||
else
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to DateTime" ).arg( value.toString() ) );
|
||||
return QDateTime();
|
||||
}
|
||||
}
|
||||
|
||||
static QDate getDateValue( const QVariant& value, QgsExpression* parent )
|
||||
{
|
||||
QDate d = value.toDate();
|
||||
if ( d.isValid() )
|
||||
{
|
||||
return d;
|
||||
}
|
||||
else
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to Date" ).arg( value.toString() ) );
|
||||
return QDate();
|
||||
}
|
||||
}
|
||||
|
||||
static QTime getTimeValue( const QVariant& value, QgsExpression* parent )
|
||||
{
|
||||
QTime t = value.toTime();
|
||||
if ( t.isValid() )
|
||||
{
|
||||
return t;
|
||||
}
|
||||
else
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to Time" ).arg( value.toString() ) );
|
||||
return QTime();
|
||||
}
|
||||
}
|
||||
|
||||
static QgsExpression::Interval getInterval( const QVariant& value, QgsExpression* parent, bool report_error = false )
|
||||
{
|
||||
if ( value.canConvert<QgsExpression::Interval>() )
|
||||
return value.value<QgsExpression::Interval>();
|
||||
|
||||
QgsExpression::Interval inter = QgsExpression::Interval::fromString( value.toString() );
|
||||
if ( inter.isValid() )
|
||||
{
|
||||
return inter;
|
||||
}
|
||||
// If we get here then we can't convert so we just error and return invalid.
|
||||
if ( report_error )
|
||||
parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to Interval" ).arg( value.toString() ) );
|
||||
|
||||
return QgsExpression::Interval::invalidInterVal();
|
||||
}
|
||||
|
||||
|
||||
// this handles also NULL values
|
||||
static TVL getTVLValue( const QVariant& value, QgsExpression* parent )
|
||||
@ -270,6 +424,12 @@ static QVariant fcnToString( const QVariantList& values, QgsFeature* , QgsExpres
|
||||
{
|
||||
return QVariant( getStringValue( values.at( 0 ), parent ) );
|
||||
}
|
||||
|
||||
static QVariant fcnToDateTime( const QVariantList& values, QgsFeature* , QgsExpression* parent )
|
||||
{
|
||||
return QVariant( getDateTimeValue( values.at( 0 ), parent ) );
|
||||
}
|
||||
|
||||
static QVariant fcnCoalesce( const QVariantList& values, QgsFeature* , QgsExpression* )
|
||||
{
|
||||
foreach( const QVariant &value, values )
|
||||
@ -344,6 +504,140 @@ static QVariant fcnConcat( const QVariantList& values, QgsFeature* , QgsExpressi
|
||||
return concat;
|
||||
}
|
||||
|
||||
static QVariant fcnNow( const QVariantList&, QgsFeature* , QgsExpression * )
|
||||
{
|
||||
return QVariant( QDateTime::currentDateTime() );
|
||||
}
|
||||
|
||||
static QVariant fcnToDate( const QVariantList& values, QgsFeature* , QgsExpression * parent )
|
||||
{
|
||||
return QVariant( getDateValue( values.at( 0 ), parent ) );
|
||||
}
|
||||
|
||||
static QVariant fcnToTime( const QVariantList& values, QgsFeature* , QgsExpression * parent )
|
||||
{
|
||||
return QVariant( getTimeValue( values.at( 0 ), parent ) );
|
||||
}
|
||||
|
||||
static QVariant fcnToInterval( const QVariantList& values, QgsFeature* , QgsExpression * parent )
|
||||
{
|
||||
return QVariant::fromValue( getInterval( values.at( 0 ), parent ) );
|
||||
}
|
||||
|
||||
static QVariant fcnAge( const QVariantList& values, QgsFeature* , QgsExpression *parent )
|
||||
{
|
||||
QDateTime d1 = getDateTimeValue( values.at( 0 ), parent );
|
||||
QDateTime d2 = getDateTimeValue( values.at( 1 ), parent );
|
||||
int seconds = d2.secsTo( d1 );
|
||||
return QVariant::fromValue( QgsExpression::Interval( seconds ) );
|
||||
}
|
||||
|
||||
static QVariant fcnDay( const QVariantList& values, QgsFeature* , QgsExpression *parent )
|
||||
{
|
||||
QVariant value = values.at( 0 );
|
||||
QgsExpression::Interval inter = getInterval( value, parent, false );
|
||||
if ( inter.isValid() )
|
||||
{
|
||||
return QVariant( inter.days() );
|
||||
}
|
||||
else
|
||||
{
|
||||
QDateTime d1 = getDateTimeValue( value, parent );
|
||||
return QVariant( d1.date().day() );
|
||||
}
|
||||
}
|
||||
|
||||
static QVariant fcnYear( const QVariantList& values, QgsFeature* , QgsExpression *parent )
|
||||
{
|
||||
QVariant value = values.at( 0 );
|
||||
QgsExpression::Interval inter = getInterval( value, parent, false );
|
||||
if ( inter.isValid() )
|
||||
{
|
||||
return QVariant( inter.years() );
|
||||
}
|
||||
else
|
||||
{
|
||||
QDateTime d1 = getDateTimeValue( value, parent );
|
||||
return QVariant( d1.date().year() );
|
||||
}
|
||||
}
|
||||
|
||||
static QVariant fcnMonth( const QVariantList& values, QgsFeature* , QgsExpression *parent )
|
||||
{
|
||||
QVariant value = values.at( 0 );
|
||||
QgsExpression::Interval inter = getInterval( value, parent, false );
|
||||
if ( inter.isValid() )
|
||||
{
|
||||
return QVariant( inter.months() );
|
||||
}
|
||||
else
|
||||
{
|
||||
QDateTime d1 = getDateTimeValue( value, parent );
|
||||
return QVariant( d1.date().month() );
|
||||
}
|
||||
}
|
||||
|
||||
static QVariant fcnWeek( const QVariantList& values, QgsFeature* , QgsExpression *parent )
|
||||
{
|
||||
QVariant value = values.at( 0 );
|
||||
QgsExpression::Interval inter = getInterval( value, parent, false );
|
||||
if ( inter.isValid() )
|
||||
{
|
||||
return QVariant( inter.weeks() );
|
||||
}
|
||||
else
|
||||
{
|
||||
QDateTime d1 = getDateTimeValue( value, parent );
|
||||
return QVariant( d1.date().weekNumber() );
|
||||
}
|
||||
}
|
||||
|
||||
static QVariant fcnHour( const QVariantList& values, QgsFeature* , QgsExpression *parent )
|
||||
{
|
||||
QVariant value = values.at( 0 );
|
||||
QgsExpression::Interval inter = getInterval( value, parent, false );
|
||||
if ( inter.isValid() )
|
||||
{
|
||||
return QVariant( inter.hours() );
|
||||
}
|
||||
else
|
||||
{
|
||||
QDateTime d1 = getDateTimeValue( value, parent );
|
||||
return QVariant( d1.time().hour() );
|
||||
}
|
||||
}
|
||||
|
||||
static QVariant fcnMinute( const QVariantList& values, QgsFeature* , QgsExpression *parent )
|
||||
{
|
||||
QVariant value = values.at( 0 );
|
||||
QgsExpression::Interval inter = getInterval( value, parent, false );
|
||||
if ( inter.isValid() )
|
||||
{
|
||||
return QVariant( inter.minutes() );
|
||||
}
|
||||
else
|
||||
{
|
||||
QDateTime d1 = getDateTimeValue( value, parent );
|
||||
return QVariant( d1.time().minute() );
|
||||
}
|
||||
}
|
||||
|
||||
static QVariant fcnSeconds( const QVariantList& values, QgsFeature* , QgsExpression *parent )
|
||||
{
|
||||
QVariant value = values.at( 0 );
|
||||
QgsExpression::Interval inter = getInterval( value, parent, false );
|
||||
if ( inter.isValid() )
|
||||
{
|
||||
return QVariant( inter.seconds() );
|
||||
}
|
||||
else
|
||||
{
|
||||
QDateTime d1 = getDateTimeValue( value, parent );
|
||||
return QVariant( d1.time().second() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define ENSURE_GEOM_TYPE(f, g, geomtype) if (!f) return QVariant(); \
|
||||
QgsGeometry* g = f->geometry(); \
|
||||
if (!g || g->type() != geomtype) return QVariant();
|
||||
@ -450,7 +744,21 @@ const QList<QgsExpression::FunctionDef> &QgsExpression::BuiltinFunctions()
|
||||
<< FunctionDef( "toint", 1, fcnToInt, QObject::tr( "Conversions" ) )
|
||||
<< FunctionDef( "toreal", 1, fcnToReal, QObject::tr( "Conversions" ) )
|
||||
<< FunctionDef( "tostring", 1, fcnToString, QObject::tr( "Conversions" ) )
|
||||
<< FunctionDef( "todatetime", 1, fcnToDateTime, QObject::tr( "Conversions" ) )
|
||||
<< FunctionDef( "todate", 1, fcnToDate, QObject::tr( "Conversions" ) )
|
||||
<< FunctionDef( "totime", 1, fcnToTime, QObject::tr( "Conversions" ) )
|
||||
<< FunctionDef( "tointerval", 1, fcnToInterval, QObject::tr( "Conversions" ) )
|
||||
<< FunctionDef( "coalesce", -1, fcnCoalesce, QObject::tr( "Conversions" ) )
|
||||
// date/time
|
||||
<< FunctionDef( "$now", 0, fcnNow, QObject::tr( "Date/Time" ) )
|
||||
<< FunctionDef( "age", 2, fcnAge, QObject::tr( "Date/Time" ) )
|
||||
<< FunctionDef( "year", 1, fcnYear, QObject::tr( "Date/Time" ) )
|
||||
<< FunctionDef( "month", 1, fcnMonth, QObject::tr( "Date/Time" ) )
|
||||
<< FunctionDef( "week", 1, fcnWeek, QObject::tr( "Date/Time" ) )
|
||||
<< FunctionDef( "day", 1, fcnDay, QObject::tr( "Date/Time" ) )
|
||||
<< FunctionDef( "hour", 1, fcnHour, QObject::tr( "Date/Time" ) )
|
||||
<< FunctionDef( "minute", 1, fcnMinute, QObject::tr( "Date/Time" ) )
|
||||
<< FunctionDef( "second", 1, fcnSeconds, QObject::tr( "Date/Time" ) )
|
||||
// string manipulation
|
||||
<< FunctionDef( "lower", 1, fcnLower, QObject::tr( "String" ) )
|
||||
<< FunctionDef( "upper", 1, fcnUpper, QObject::tr( "String" ) )
|
||||
@ -905,6 +1213,17 @@ QVariant QgsExpression::NodeBinaryOperator::eval( QgsExpression* parent, QgsFeat
|
||||
if ( mOp == boDiv && iR == 0 ) return QVariant(); // silently handle division by zero and return NULL
|
||||
return QVariant( computeInt( iL, iR ) );
|
||||
}
|
||||
else if ( isDateTimeSafe( vL ) && isIntervalSafe( vR ) )
|
||||
{
|
||||
QDateTime dL = getDateTimeValue( vL, parent ); ENSURE_NO_EVAL_ERROR;
|
||||
QgsExpression::Interval iL = getInterval( vR, parent ); ENSURE_NO_EVAL_ERROR;
|
||||
if ( mOp == boDiv || mOp == boMul || mOp == boMod )
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr("Can't preform /, *, or % on DateTime and Interval") );
|
||||
return QVariant();
|
||||
}
|
||||
return QVariant( computeDateTimeFromInterval( dL, &iL ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// general floating point arithmetic
|
||||
@ -1068,6 +1387,16 @@ int QgsExpression::NodeBinaryOperator::computeInt( int x, int y )
|
||||
}
|
||||
}
|
||||
|
||||
QDateTime QgsExpression::NodeBinaryOperator::computeDateTimeFromInterval( QDateTime d, QgsExpression::Interval *i )
|
||||
{
|
||||
switch ( mOp )
|
||||
{
|
||||
case boPlus: return d.addSecs( i->seconds() );
|
||||
case boMinus: return d.addSecs( -i->seconds() );
|
||||
default: Q_ASSERT( false ); return QDateTime();
|
||||
}
|
||||
}
|
||||
|
||||
double QgsExpression::NodeBinaryOperator::computeDouble( double x, double y )
|
||||
{
|
||||
switch ( mOp )
|
||||
|
@ -16,6 +16,7 @@
|
||||
#ifndef QGSEXPRESSION_H
|
||||
#define QGSEXPRESSION_H
|
||||
|
||||
#include <QMetaType>
|
||||
#include <QStringList>
|
||||
#include <QVariant>
|
||||
#include <QList>
|
||||
@ -256,6 +257,36 @@ class CORE_EXPORT QgsExpression
|
||||
QList<Node*> mList;
|
||||
};
|
||||
|
||||
class CORE_EXPORT Interval
|
||||
{
|
||||
// YEAR const value taken from postgres query
|
||||
// SELECT EXTRACT(EPOCH FROM interval '1 year')
|
||||
static const double YEARS = ( 31557600 );
|
||||
static const double MONTHS = ( 60 * 60 * 24 * 30 );
|
||||
static const double WEEKS = ( 60 * 60 * 24 * 7 );
|
||||
static const double DAY = ( 60 * 60 * 24 );
|
||||
static const double HOUR = ( 60 * 60 );
|
||||
static const double MINUTE = ( 60 );
|
||||
public:
|
||||
Interval( double seconds = 0 ) { mSeconds = seconds; }
|
||||
~Interval();
|
||||
double years() { return mSeconds / YEARS;}
|
||||
double months() { return mSeconds / MONTHS; }
|
||||
double weeks() { return mSeconds / WEEKS;}
|
||||
double days() { return mSeconds / DAY;}
|
||||
double hours() { return mSeconds / HOUR;}
|
||||
double minutes() { return mSeconds / MINUTE;}
|
||||
bool isValid() { return mValid; }
|
||||
void setValid( bool valid ) { mValid = valid; }
|
||||
double seconds() { return mSeconds; }
|
||||
bool operator==( const QgsExpression::Interval& other ) const;
|
||||
static QgsExpression::Interval invalidInterVal();
|
||||
static QgsExpression::Interval fromString( QString string );
|
||||
private:
|
||||
double mSeconds;
|
||||
bool mValid;
|
||||
};
|
||||
|
||||
class CORE_EXPORT NodeUnaryOperator : public Node
|
||||
{
|
||||
public:
|
||||
@ -306,6 +337,7 @@ class CORE_EXPORT QgsExpression
|
||||
bool compare( double diff );
|
||||
int computeInt( int x, int y );
|
||||
double computeDouble( double x, double y );
|
||||
QDateTime computeDateTimeFromInterval( QDateTime d, QgsExpression::Interval *i );
|
||||
|
||||
BinaryOperator mOp;
|
||||
Node* mOpLeft;
|
||||
@ -483,4 +515,6 @@ class CORE_EXPORT QgsExpression
|
||||
QgsDistanceArea* mCalc;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE( QgsExpression::Interval )
|
||||
|
||||
#endif // QGSEXPRESSION_H
|
||||
|
@ -165,7 +165,8 @@ expression:
|
||||
exp_error("Function is not known");
|
||||
YYERROR;
|
||||
}
|
||||
if ( QgsExpression::BuiltinFunctions()[fnIndex].mParams != -1 && QgsExpression::BuiltinFunctions()[fnIndex].mParams != $3->count() )
|
||||
if ( QgsExpression::BuiltinFunctions()[fnIndex].mParams != -1
|
||||
&& QgsExpression::BuiltinFunctions()[fnIndex].mParams != $3->count() )
|
||||
{
|
||||
exp_error("Function is called with wrong number of arguments");
|
||||
YYERROR;
|
||||
|
@ -270,6 +270,18 @@ class TestQgsExpression: public QObject
|
||||
QTest::newRow( "condition else" ) << "case when 1=0 then 'bad' else 678 end" << false << QVariant( 678 );
|
||||
QTest::newRow( "condition null" ) << "case when length(123)=0 then 111 end" << false << QVariant();
|
||||
QTest::newRow( "condition 2 when" ) << "case when 2>3 then 23 when 3>2 then 32 else 0 end" << false << QVariant( 32 );
|
||||
|
||||
// Datetime functions
|
||||
QTest::newRow( "to date" ) << "todate('2012-06-28')" << false << QVariant( QDate( 2012, 06, 28 ) );
|
||||
QTest::newRow( "to interval" ) << "tointerval('1 Year 1 Month 1 Week 1 Hour 1 Minute')" << false << QVariant::fromValue( QgsExpression::Interval( 34758060 ) );
|
||||
QTest::newRow( "day with date" ) << "day('2012-06-28')" << false << QVariant( 28 );
|
||||
QTest::newRow( "day with interval" ) << "day(tointerval('28 days'))" << false << QVariant( 28.0 );
|
||||
QTest::newRow( "month with date" ) << "month('2012-06-28')" << false << QVariant( 6 );
|
||||
QTest::newRow( "month with interval" ) << "month(tointerval('2 months'))" << false << QVariant( 2.0 );
|
||||
QTest::newRow( "year with date" ) << "year('2012-06-28')" << false << QVariant( 2012 );
|
||||
QTest::newRow( "year with interval" ) << "year(tointerval('2 years'))" << false << QVariant( 2.0 );
|
||||
QTest::newRow( "age" ) << "age('2012-06-30','2012-06-28')" << false << QVariant::fromValue( QgsExpression::Interval( 172800 ) );
|
||||
QTest::newRow( "negative age" ) << "age('2012-06-28','2012-06-30')" << false << QVariant::fromValue( QgsExpression::Interval( -172800 ) );
|
||||
}
|
||||
|
||||
void evaluation()
|
||||
@ -280,6 +292,8 @@ class TestQgsExpression: public QObject
|
||||
|
||||
QgsExpression exp( string );
|
||||
QCOMPARE( exp.hasParserError(), false );
|
||||
if ( exp.hasParserError() )
|
||||
qDebug() << exp.parserErrorString();
|
||||
|
||||
QVariant res = exp.evaluate();
|
||||
if ( exp.hasEvalError() )
|
||||
@ -305,6 +319,22 @@ class TestQgsExpression: public QObject
|
||||
case QVariant::String:
|
||||
QCOMPARE( res.toString(), result.toString() );
|
||||
break;
|
||||
case QVariant::Date:
|
||||
QCOMPARE( res.toDate(), result.toDate() );
|
||||
break;
|
||||
case QVariant::DateTime:
|
||||
QCOMPARE( res.toDateTime(), result.toDateTime() );
|
||||
break;
|
||||
case QVariant::Time:
|
||||
QCOMPARE( res.toTime(), result.toTime() );
|
||||
break;
|
||||
case QVariant::UserType:
|
||||
{
|
||||
QgsExpression::Interval inter = res.value<QgsExpression::Interval>();
|
||||
QgsExpression::Interval gotinter = result.value<QgsExpression::Interval>();
|
||||
QCOMPARE( inter.seconds(), gotinter.seconds() );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Q_ASSERT( false ); // should never happen
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user