mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
New class QgsInterval for storing durations between datetimes
Move the QgsExpression::Interval class out to its own QgsInterval class, extend with new methods and add tests Add a typedef to keep API compatibility for 2.16
This commit is contained in:
parent
3340d8ea70
commit
ceba5264f7
@ -57,6 +57,7 @@
|
||||
%Include qgsgml.sip
|
||||
%Include qgsgmlschema.sip
|
||||
%Include qgshistogram.sip
|
||||
%Include qgsinterval.sip
|
||||
%Include qgsjsonutils.sip
|
||||
%Include qgsmaptopixelgeometrysimplifier.sip
|
||||
%Include qgstransaction.sip
|
||||
|
@ -671,33 +671,33 @@ class QgsExpression
|
||||
virtual QString dump() const;
|
||||
};
|
||||
|
||||
//TODO QGIS 3.0 - remove
|
||||
//! @deprecated use QgsInterval instead
|
||||
class Interval
|
||||
{
|
||||
{
|
||||
public:
|
||||
Interval( int seconds = 0 );
|
||||
|
||||
//! interval length in years
|
||||
double years();
|
||||
double years() const;
|
||||
//! interval length in months
|
||||
double months();
|
||||
double months() const;
|
||||
//! interval length in weeks
|
||||
double weeks();
|
||||
double weeks() const;
|
||||
//! interval length in days
|
||||
double days();
|
||||
double days() const;
|
||||
//! interval length in hours
|
||||
double hours();
|
||||
double hours() const;
|
||||
//! interval length in minutus
|
||||
double minutes();
|
||||
double minutes() const;
|
||||
//! interval length in seconds
|
||||
double seconds();
|
||||
double seconds() const;
|
||||
//! getter interval validity
|
||||
bool isValid();
|
||||
bool isValid() const;
|
||||
//! setter interval validity
|
||||
void setValid( bool valid );
|
||||
//! compare two intervals
|
||||
bool operator==( QgsExpression::Interval other ) const;
|
||||
//! return an invalid interval
|
||||
static QgsExpression::Interval invalidInterVal();
|
||||
//! convert a string to an interval
|
||||
static QgsExpression::Interval fromString( const QString& string );
|
||||
};
|
||||
@ -749,7 +749,12 @@ class QgsExpression
|
||||
bool compare( double diff );
|
||||
int computeInt( int x, int y );
|
||||
double computeDouble( double x, double y );
|
||||
QDateTime computeDateTimeFromInterval( const QDateTime& d, QgsExpression::Interval *i );
|
||||
|
||||
/** Computes the result date time calculation from a start datetime and an interval
|
||||
* @param d start datetime
|
||||
* @param i interval to add or subtract (depending on mOp)
|
||||
*/
|
||||
QDateTime computeDateTimeFromInterval( const QDateTime& d, QgsInterval *i );
|
||||
};
|
||||
|
||||
class NodeInOperator : QgsExpression::Node
|
||||
|
136
python/core/qgsinterval.sip
Normal file
136
python/core/qgsinterval.sip
Normal file
@ -0,0 +1,136 @@
|
||||
/** \ingroup core
|
||||
* \class QgsInterval
|
||||
* \brief A representation of the interval between two datetime values.
|
||||
* \note Added in version 2.16
|
||||
*/
|
||||
|
||||
class QgsInterval
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include <qgsinterval.h>
|
||||
%End
|
||||
|
||||
public:
|
||||
|
||||
// YEAR const value taken from postgres query
|
||||
// SELECT EXTRACT(EPOCH FROM interval '1 year')
|
||||
//! Seconds per year (average)
|
||||
static const int YEARS;
|
||||
//! Seconds per month, based on 30 day month
|
||||
static const int MONTHS;
|
||||
//! Seconds per week
|
||||
static const int WEEKS;
|
||||
//! Seconds per day
|
||||
static const int DAY;
|
||||
//! Seconds per hour
|
||||
static const int HOUR;
|
||||
//! Seconds per minute
|
||||
static const int MINUTE;
|
||||
|
||||
/** Default constructor for QgsInterval. Creates an invalid interval.
|
||||
*/
|
||||
QgsInterval();
|
||||
|
||||
/** Constructor for QgsInterval.
|
||||
* @param seconds duration of interval in seconds
|
||||
*/
|
||||
QgsInterval( double seconds );
|
||||
|
||||
/** Returns the interval duration in years (based on an average year length)
|
||||
* @see setYears()
|
||||
*/
|
||||
double years() const;
|
||||
|
||||
/** Sets the interval duration in years.
|
||||
* @param years duration in years (based on average year length)
|
||||
* @see years()
|
||||
*/
|
||||
void setYears( double years );
|
||||
|
||||
/** Returns the interval duration in months (based on a 30 day month).
|
||||
* @see setMonths()
|
||||
*/
|
||||
double months() const;
|
||||
|
||||
/** Sets the interval duration in months.
|
||||
* @param months duration in months (based on a 30 day month)
|
||||
* @see months()
|
||||
*/
|
||||
void setMonths( double months );
|
||||
|
||||
/** Returns the interval duration in weeks.
|
||||
* @see setWeeks()
|
||||
*/
|
||||
double weeks() const;
|
||||
|
||||
/** Sets the interval duration in weeks.
|
||||
* @param weeks duration in weeks
|
||||
* @see weeks()
|
||||
*/
|
||||
void setWeeks( double weeks );
|
||||
|
||||
/** Returns the interval duration in days.
|
||||
* @see setDays()
|
||||
*/
|
||||
double days() const;
|
||||
|
||||
/** Sets the interval duration in days.
|
||||
* @param days duration in days
|
||||
* @see days()
|
||||
*/
|
||||
void setDays( double days );
|
||||
|
||||
/** Returns the interval duration in hours.
|
||||
* @see setHours()
|
||||
*/
|
||||
double hours() const;
|
||||
|
||||
/** Sets the interval duration in hours.
|
||||
* @param hours duration in hours
|
||||
* @see hours()
|
||||
*/
|
||||
void setHours( double hours );
|
||||
|
||||
/** Returns the interval duration in minutes.
|
||||
* @see setMinutes()
|
||||
*/
|
||||
double minutes() const;
|
||||
|
||||
/** Sets the interval duration in minutes.
|
||||
* @param minutes duration in minutes
|
||||
* @see minutes()
|
||||
*/
|
||||
void setMinutes( double minutes );
|
||||
|
||||
/** Returns the interval duration in seconds.
|
||||
* @see setSeconds()
|
||||
*/
|
||||
double seconds() const;
|
||||
|
||||
/** Sets the interval duration in seconds.
|
||||
* @param seconds duration in seconds
|
||||
* @see seconds()
|
||||
*/
|
||||
void setSeconds( double seconds );
|
||||
|
||||
/** Returns true if the interval is valid.
|
||||
* @see setValid()
|
||||
*/
|
||||
bool isValid() const;
|
||||
|
||||
/** Sets whether the interval is valid.
|
||||
* @param valid set to true to set the interval as valid.
|
||||
* @see isValid()
|
||||
*/
|
||||
void setValid( bool valid );
|
||||
|
||||
bool operator==( const QgsInterval& other ) const;
|
||||
|
||||
/** Converts a string to an interval
|
||||
* @param string string to parse
|
||||
* @returns interval, or invalid interval if string could not be parsed
|
||||
*/
|
||||
static QgsInterval fromString( const QString& string );
|
||||
|
||||
};
|
||||
|
@ -121,6 +121,7 @@ SET(QGIS_CORE_SRCS
|
||||
qgsgml.cpp
|
||||
qgsgmlschema.cpp
|
||||
qgshistogram.cpp
|
||||
qgsinterval.cpp
|
||||
qgsjsonutils.cpp
|
||||
qgslabel.cpp
|
||||
qgslabelattributes.cpp
|
||||
@ -637,6 +638,7 @@ SET(QGIS_CORE_HDRS
|
||||
qgsgeometrycache.h
|
||||
qgshistogram.h
|
||||
qgsindexedfeature.h
|
||||
qgsinterval.h
|
||||
qgsjsonutils.h
|
||||
qgslayerdefinition.h
|
||||
qgslabel.h
|
||||
|
@ -57,79 +57,6 @@
|
||||
// from parser
|
||||
extern QgsExpression::Node* parseExpression( const QString& str, QString& parserErrorMsg );
|
||||
|
||||
QgsExpression::Interval QgsExpression::Interval::invalidInterVal()
|
||||
{
|
||||
QgsExpression::Interval inter = QgsExpression::Interval();
|
||||
inter.setValid( false );
|
||||
return inter;
|
||||
}
|
||||
|
||||
QgsExpression::Interval QgsExpression::Interval::fromString( const QString& string )
|
||||
{
|
||||
int seconds = 0;
|
||||
QRegExp rx( "([-+]?\\d?\\.?\\d+\\s+\\S+)", Qt::CaseInsensitive );
|
||||
QStringList list;
|
||||
int pos = 0;
|
||||
|
||||
while (( pos = rx.indexIn( string, pos ) ) != -1 )
|
||||
{
|
||||
list << rx.cap( 1 );
|
||||
pos += rx.matchedLength();
|
||||
}
|
||||
|
||||
QMap<int, QStringList> map;
|
||||
map.insert( 1, QStringList() << "second" << "seconds" << tr( "second|seconds", "list of words separated by | which reference years" ).split( '|' ) );
|
||||
map.insert( 0 + MINUTE, QStringList() << "minute" << "minutes" << tr( "minute|minutes", "list of words separated by | which reference minutes" ).split( '|' ) );
|
||||
map.insert( 0 + HOUR, QStringList() << "hour" << "hours" << tr( "hour|hours", "list of words separated by | which reference minutes hours" ).split( '|' ) );
|
||||
map.insert( 0 + DAY, QStringList() << "day" << "days" << tr( "day|days", "list of words separated by | which reference days" ).split( '|' ) );
|
||||
map.insert( 0 + WEEKS, QStringList() << "week" << "weeks" << tr( "week|weeks", "wordlist separated by | which reference weeks" ).split( '|' ) );
|
||||
map.insert( 0 + MONTHS, QStringList() << "month" << "months" << tr( "month|months", "list of words separated by | which reference months" ).split( '|' ) );
|
||||
map.insert( 0 + YEARS, QStringList() << "year" << "years" << tr( "year|years", "list of words separated by | which reference years" ).split( '|' ) );
|
||||
|
||||
Q_FOREACH ( const QString& match, list )
|
||||
{
|
||||
QStringList split = match.split( QRegExp( "\\s+" ) );
|
||||
bool ok;
|
||||
double value = split.at( 0 ).toDouble( &ok );
|
||||
if ( !ok )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bool matched = false;
|
||||
QMap<int, QStringList>::const_iterator it = map.constBegin();
|
||||
for ( ; it != map.constEnd(); ++it )
|
||||
{
|
||||
int duration = it.key();
|
||||
Q_FOREACH ( const QString& name, it.value() )
|
||||
{
|
||||
if ( match.contains( name, Qt::CaseInsensitive ) )
|
||||
{
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( matched )
|
||||
{
|
||||
seconds += value * duration;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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==( QgsExpression::Interval other ) const
|
||||
{
|
||||
return qgsDoubleNear( mSeconds, other.mSeconds );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// three-value logic
|
||||
|
||||
@ -213,14 +140,14 @@ inline bool isDateTimeSafe( const QVariant& v )
|
||||
|
||||
inline bool isIntervalSafe( const QVariant& v )
|
||||
{
|
||||
if ( v.canConvert<QgsExpression::Interval>() )
|
||||
if ( v.canConvert<QgsInterval>() )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( v.type() == QVariant::String )
|
||||
{
|
||||
return QgsExpression::Interval::fromString( v.toString() ).isValid();
|
||||
return QgsInterval::fromString( v.toString() ).isValid();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -335,12 +262,12 @@ static QTime getTimeValue( const QVariant& value, QgsExpression* parent )
|
||||
}
|
||||
}
|
||||
|
||||
static QgsExpression::Interval getInterval( const QVariant& value, QgsExpression* parent, bool report_error = false )
|
||||
static QgsInterval getInterval( const QVariant& value, QgsExpression* parent, bool report_error = false )
|
||||
{
|
||||
if ( value.canConvert<QgsExpression::Interval>() )
|
||||
return value.value<QgsExpression::Interval>();
|
||||
if ( value.canConvert<QgsInterval>() )
|
||||
return value.value<QgsInterval>();
|
||||
|
||||
QgsExpression::Interval inter = QgsExpression::Interval::fromString( value.toString() );
|
||||
QgsInterval inter = QgsInterval::fromString( value.toString() );
|
||||
if ( inter.isValid() )
|
||||
{
|
||||
return inter;
|
||||
@ -349,7 +276,7 @@ static QgsExpression::Interval getInterval( const QVariant& value, QgsExpression
|
||||
if ( report_error )
|
||||
parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to Interval" ).arg( value.toString() ) );
|
||||
|
||||
return QgsExpression::Interval::invalidInterVal();
|
||||
return QgsInterval();
|
||||
}
|
||||
|
||||
static QgsGeometry getGeometry( const QVariant& value, QgsExpression* parent )
|
||||
@ -1116,7 +1043,7 @@ static QVariant fcnAge( const QVariantList& values, const QgsExpressionContext*,
|
||||
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 ) );
|
||||
return QVariant::fromValue( QgsInterval( seconds ) );
|
||||
}
|
||||
|
||||
static QVariant fcnDayOfWeek( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
|
||||
@ -1136,7 +1063,7 @@ static QVariant fcnDayOfWeek( const QVariantList& values, const QgsExpressionCon
|
||||
static QVariant fcnDay( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
|
||||
{
|
||||
QVariant value = values.at( 0 );
|
||||
QgsExpression::Interval inter = getInterval( value, parent, false );
|
||||
QgsInterval inter = getInterval( value, parent, false );
|
||||
if ( inter.isValid() )
|
||||
{
|
||||
return QVariant( inter.days() );
|
||||
@ -1151,7 +1078,7 @@ static QVariant fcnDay( const QVariantList& values, const QgsExpressionContext*,
|
||||
static QVariant fcnYear( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
|
||||
{
|
||||
QVariant value = values.at( 0 );
|
||||
QgsExpression::Interval inter = getInterval( value, parent, false );
|
||||
QgsInterval inter = getInterval( value, parent, false );
|
||||
if ( inter.isValid() )
|
||||
{
|
||||
return QVariant( inter.years() );
|
||||
@ -1166,7 +1093,7 @@ static QVariant fcnYear( const QVariantList& values, const QgsExpressionContext*
|
||||
static QVariant fcnMonth( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
|
||||
{
|
||||
QVariant value = values.at( 0 );
|
||||
QgsExpression::Interval inter = getInterval( value, parent, false );
|
||||
QgsInterval inter = getInterval( value, parent, false );
|
||||
if ( inter.isValid() )
|
||||
{
|
||||
return QVariant( inter.months() );
|
||||
@ -1181,7 +1108,7 @@ static QVariant fcnMonth( const QVariantList& values, const QgsExpressionContext
|
||||
static QVariant fcnWeek( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
|
||||
{
|
||||
QVariant value = values.at( 0 );
|
||||
QgsExpression::Interval inter = getInterval( value, parent, false );
|
||||
QgsInterval inter = getInterval( value, parent, false );
|
||||
if ( inter.isValid() )
|
||||
{
|
||||
return QVariant( inter.weeks() );
|
||||
@ -1196,7 +1123,7 @@ static QVariant fcnWeek( const QVariantList& values, const QgsExpressionContext*
|
||||
static QVariant fcnHour( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
|
||||
{
|
||||
QVariant value = values.at( 0 );
|
||||
QgsExpression::Interval inter = getInterval( value, parent, false );
|
||||
QgsInterval inter = getInterval( value, parent, false );
|
||||
if ( inter.isValid() )
|
||||
{
|
||||
return QVariant( inter.hours() );
|
||||
@ -1211,7 +1138,7 @@ static QVariant fcnHour( const QVariantList& values, const QgsExpressionContext*
|
||||
static QVariant fcnMinute( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
|
||||
{
|
||||
QVariant value = values.at( 0 );
|
||||
QgsExpression::Interval inter = getInterval( value, parent, false );
|
||||
QgsInterval inter = getInterval( value, parent, false );
|
||||
if ( inter.isValid() )
|
||||
{
|
||||
return QVariant( inter.minutes() );
|
||||
@ -1226,7 +1153,7 @@ static QVariant fcnMinute( const QVariantList& values, const QgsExpressionContex
|
||||
static QVariant fcnSeconds( const QVariantList& values, const QgsExpressionContext*, QgsExpression *parent )
|
||||
{
|
||||
QVariant value = values.at( 0 );
|
||||
QgsExpression::Interval inter = getInterval( value, parent, false );
|
||||
QgsInterval inter = getInterval( value, parent, false );
|
||||
if ( inter.isValid() )
|
||||
{
|
||||
return QVariant( inter.seconds() );
|
||||
@ -3704,7 +3631,7 @@ QVariant QgsExpression::NodeBinaryOperator::eval( QgsExpression *parent, const Q
|
||||
{
|
||||
QDateTime dL = getDateTimeValue( vL, parent );
|
||||
ENSURE_NO_EVAL_ERROR;
|
||||
QgsExpression::Interval iL = getInterval( vR, parent );
|
||||
QgsInterval iL = getInterval( vR, parent );
|
||||
ENSURE_NO_EVAL_ERROR;
|
||||
if ( mOp == boDiv || mOp == boMul || mOp == boMod )
|
||||
{
|
||||
@ -3920,7 +3847,7 @@ int QgsExpression::NodeBinaryOperator::computeInt( int x, int y )
|
||||
}
|
||||
}
|
||||
|
||||
QDateTime QgsExpression::NodeBinaryOperator::computeDateTimeFromInterval( const QDateTime& d, QgsExpression::Interval *i )
|
||||
QDateTime QgsExpression::NodeBinaryOperator::computeDateTimeFromInterval( const QDateTime& d, QgsInterval *i )
|
||||
{
|
||||
switch ( mOp )
|
||||
{
|
||||
@ -4685,10 +4612,10 @@ QString QgsExpression::formatPreviewString( const QVariant& value )
|
||||
QgsFeature feat = value.value<QgsFeature>();
|
||||
return tr( "<i><feature: %1></i>" ).arg( feat.id() );
|
||||
}
|
||||
else if ( value.canConvert< QgsExpression::Interval >() )
|
||||
else if ( value.canConvert< QgsInterval >() )
|
||||
{
|
||||
//result is a feature
|
||||
QgsExpression::Interval interval = value.value<QgsExpression::Interval>();
|
||||
QgsInterval interval = value.value<QgsInterval>();
|
||||
return tr( "<i><interval: %1 days></i>" ).arg( interval.days() );
|
||||
}
|
||||
else if ( value.type() == QVariant::Date )
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include "qgis.h"
|
||||
#include "qgsunittypes.h"
|
||||
#include "qgsinterval.h"
|
||||
|
||||
class QgsFeature;
|
||||
class QgsGeometry;
|
||||
@ -959,51 +960,9 @@ class CORE_EXPORT QgsExpression
|
||||
bool mHasNamedNodes;
|
||||
};
|
||||
|
||||
class CORE_EXPORT Interval
|
||||
{
|
||||
// YEAR const value taken from postgres query
|
||||
// SELECT EXTRACT(EPOCH FROM interval '1 year')
|
||||
static const int YEARS = 31557600;
|
||||
static const int MONTHS = 60 * 60 * 24 * 30;
|
||||
static const int WEEKS = 60 * 60 * 24 * 7;
|
||||
static const int DAY = 60 * 60 * 24;
|
||||
static const int HOUR = 60 * 60;
|
||||
static const int MINUTE = 60;
|
||||
public:
|
||||
Interval( double seconds = 0 )
|
||||
: mSeconds( seconds )
|
||||
, mValid( true )
|
||||
{ }
|
||||
|
||||
//! interval length in years
|
||||
double years() { return mSeconds / YEARS;}
|
||||
//! interval length in months
|
||||
double months() { return mSeconds / MONTHS; }
|
||||
//! interval length in weeks
|
||||
double weeks() { return mSeconds / WEEKS;}
|
||||
//! interval length in days
|
||||
double days() { return mSeconds / DAY;}
|
||||
//! interval length in hours
|
||||
double hours() { return mSeconds / HOUR;}
|
||||
//! interval length in minutus
|
||||
double minutes() { return mSeconds / MINUTE;}
|
||||
//! interval length in seconds
|
||||
double seconds() { return mSeconds; }
|
||||
//! getter interval validity
|
||||
bool isValid() { return mValid; }
|
||||
//! setter interval validity
|
||||
void setValid( bool valid ) { mValid = valid; }
|
||||
//! compare two intervals
|
||||
bool operator==( QgsExpression::Interval other ) const;
|
||||
//! return an invalid interval
|
||||
static QgsExpression::Interval invalidInterVal();
|
||||
//! convert a string to an interval
|
||||
static QgsExpression::Interval fromString( const QString& string );
|
||||
|
||||
private:
|
||||
double mSeconds;
|
||||
bool mValid;
|
||||
};
|
||||
//TODO QGIS 3.0 - remove
|
||||
//! @deprecated use QgsInterval instead
|
||||
typedef QgsInterval Interval;
|
||||
|
||||
class CORE_EXPORT NodeUnaryOperator : public Node
|
||||
{
|
||||
@ -1063,7 +1022,12 @@ class CORE_EXPORT QgsExpression
|
||||
bool compare( double diff );
|
||||
int computeInt( int x, int y );
|
||||
double computeDouble( double x, double y );
|
||||
QDateTime computeDateTimeFromInterval( const QDateTime& d, QgsExpression::Interval *i );
|
||||
|
||||
/** Computes the result date time calculation from a start datetime and an interval
|
||||
* @param d start datetime
|
||||
* @param i interval to add or subtract (depending on mOp)
|
||||
*/
|
||||
QDateTime computeDateTimeFromInterval( const QDateTime& d, QgsInterval* i );
|
||||
|
||||
BinaryOperator mOp;
|
||||
Node* mOpLeft;
|
||||
@ -1492,7 +1456,6 @@ class CORE_EXPORT QgsExpression
|
||||
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
|
||||
Q_DECLARE_METATYPE( QgsExpression::Interval )
|
||||
Q_DECLARE_METATYPE( QgsExpression::Node* )
|
||||
|
||||
#endif // QGSEXPRESSION_H
|
||||
|
131
src/core/qgsinterval.cpp
Normal file
131
src/core/qgsinterval.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
/***************************************************************************
|
||||
qgsinterval.cpp
|
||||
---------------
|
||||
Date : May 2016
|
||||
Copyright : (C) 2016 by Nyall Dawson
|
||||
Email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsinterval.h"
|
||||
#include "qgis.h"
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QMap>
|
||||
#include <QObject>
|
||||
#include <QDebug>
|
||||
|
||||
/***************************************************************************
|
||||
* This class is considered CRITICAL and any change MUST be accompanied with
|
||||
* full unit tests in test_qgsinterval.py.
|
||||
* See details in QEP #17
|
||||
****************************************************************************/
|
||||
|
||||
QgsInterval::QgsInterval()
|
||||
: mSeconds( 0.0 )
|
||||
, mValid( false )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QgsInterval::QgsInterval( double seconds )
|
||||
: mSeconds( seconds )
|
||||
, mValid( true )
|
||||
{ }
|
||||
|
||||
bool QgsInterval::operator==( const QgsInterval& other ) const
|
||||
{
|
||||
if ( !mValid && !other.mValid )
|
||||
return true;
|
||||
else if ( mValid && other.mValid )
|
||||
return qgsDoubleNear( mSeconds, other.mSeconds );
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
QgsInterval QgsInterval::fromString( const QString& string )
|
||||
{
|
||||
int seconds = 0;
|
||||
QRegExp rx( "([-+]?\\d?\\.?\\d+\\s+\\S+)", Qt::CaseInsensitive );
|
||||
QStringList list;
|
||||
int pos = 0;
|
||||
|
||||
while (( pos = rx.indexIn( string, pos ) ) != -1 )
|
||||
{
|
||||
list << rx.cap( 1 );
|
||||
pos += rx.matchedLength();
|
||||
}
|
||||
|
||||
QMap<int, QStringList> map;
|
||||
map.insert( 1, QStringList() << "second" << "seconds" << QObject::tr( "second|seconds", "list of words separated by | which reference years" ).split( '|' ) );
|
||||
map.insert( 0 + MINUTE, QStringList() << "minute" << "minutes" << QObject::tr( "minute|minutes", "list of words separated by | which reference minutes" ).split( '|' ) );
|
||||
map.insert( 0 + HOUR, QStringList() << "hour" << "hours" << QObject::tr( "hour|hours", "list of words separated by | which reference minutes hours" ).split( '|' ) );
|
||||
map.insert( 0 + DAY, QStringList() << "day" << "days" << QObject::tr( "day|days", "list of words separated by | which reference days" ).split( '|' ) );
|
||||
map.insert( 0 + WEEKS, QStringList() << "week" << "weeks" << QObject::tr( "week|weeks", "wordlist separated by | which reference weeks" ).split( '|' ) );
|
||||
map.insert( 0 + MONTHS, QStringList() << "month" << "months" << QObject::tr( "month|months", "list of words separated by | which reference months" ).split( '|' ) );
|
||||
map.insert( 0 + YEARS, QStringList() << "year" << "years" << QObject::tr( "year|years", "list of words separated by | which reference years" ).split( '|' ) );
|
||||
|
||||
Q_FOREACH ( const QString& match, list )
|
||||
{
|
||||
QStringList split = match.split( QRegExp( "\\s+" ) );
|
||||
bool ok;
|
||||
double value = split.at( 0 ).toDouble( &ok );
|
||||
if ( !ok )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bool matched = false;
|
||||
QMap<int, QStringList>::const_iterator it = map.constBegin();
|
||||
for ( ; it != map.constEnd(); ++it )
|
||||
{
|
||||
int duration = it.key();
|
||||
Q_FOREACH ( const QString& name, it.value() )
|
||||
{
|
||||
if ( match.contains( name, Qt::CaseInsensitive ) )
|
||||
{
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( matched )
|
||||
{
|
||||
seconds += value * duration;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we can't parse the string at all then we just return invalid
|
||||
if ( seconds == 0 )
|
||||
return QgsInterval();
|
||||
|
||||
return QgsInterval( seconds );
|
||||
}
|
||||
|
||||
QDebug operator<<( QDebug dbg, const QgsInterval& interval )
|
||||
{
|
||||
if ( !interval.isValid() )
|
||||
dbg.nospace() << "QgsInterval()";
|
||||
else
|
||||
dbg.nospace() << "QgsInterval(" << interval.seconds() << ")";
|
||||
return dbg.maybeSpace();
|
||||
}
|
||||
|
||||
QgsInterval operator-( const QDateTime& dt1, const QDateTime& dt2 )
|
||||
{
|
||||
qint64 mSeconds = dt2.msecsTo( dt1 );
|
||||
return QgsInterval( mSeconds / 1000.0 );
|
||||
}
|
||||
|
||||
QDateTime operator+( const QDateTime& start, const QgsInterval& interval )
|
||||
{
|
||||
return start.addMSecs( static_cast<qint64>( interval.seconds() * 1000.0 ) );
|
||||
}
|
188
src/core/qgsinterval.h
Normal file
188
src/core/qgsinterval.h
Normal file
@ -0,0 +1,188 @@
|
||||
/***************************************************************************
|
||||
qgsinterval.h
|
||||
-------------
|
||||
Date : May 2016
|
||||
Copyright : (C) 2016 by Nyall Dawson
|
||||
Email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSINTERVAL_H
|
||||
#define QGSINTERVAL_H
|
||||
|
||||
/***************************************************************************
|
||||
* This class is considered CRITICAL and any change MUST be accompanied with
|
||||
* full unit tests in test_qgsinterval.py.
|
||||
* See details in QEP #17
|
||||
****************************************************************************/
|
||||
|
||||
#include <QVariant>
|
||||
class QString;
|
||||
|
||||
/** \ingroup core
|
||||
* \class QgsInterval
|
||||
* \brief A representation of the interval between two datetime values.
|
||||
* \note Added in version 2.16
|
||||
*/
|
||||
|
||||
class CORE_EXPORT QgsInterval
|
||||
{
|
||||
public:
|
||||
|
||||
// YEAR const value taken from postgres query
|
||||
// SELECT EXTRACT(EPOCH FROM interval '1 year')
|
||||
//! Seconds per year (average)
|
||||
static const int YEARS = 31557600;
|
||||
//! Seconds per month, based on 30 day month
|
||||
static const int MONTHS = 60 * 60 * 24 * 30;
|
||||
//! Seconds per week
|
||||
static const int WEEKS = 60 * 60 * 24 * 7;
|
||||
//! Seconds per day
|
||||
static const int DAY = 60 * 60 * 24;
|
||||
//! Seconds per hour
|
||||
static const int HOUR = 60 * 60;
|
||||
//! Seconds per minute
|
||||
static const int MINUTE = 60;
|
||||
|
||||
/** Default constructor for QgsInterval. Creates an invalid interval.
|
||||
*/
|
||||
QgsInterval();
|
||||
|
||||
/** Constructor for QgsInterval.
|
||||
* @param seconds duration of interval in seconds
|
||||
*/
|
||||
QgsInterval( double seconds );
|
||||
|
||||
/** Returns the interval duration in years (based on an average year length)
|
||||
* @see setYears()
|
||||
*/
|
||||
double years() const { return mSeconds / YEARS; }
|
||||
|
||||
/** Sets the interval duration in years.
|
||||
* @param years duration in years (based on average year length)
|
||||
* @see years()
|
||||
*/
|
||||
void setYears( double years ) { mSeconds = years * YEARS; mValid = true; }
|
||||
|
||||
/** Returns the interval duration in months (based on a 30 day month).
|
||||
* @see setMonths()
|
||||
*/
|
||||
double months() const { return mSeconds / MONTHS; }
|
||||
|
||||
/** Sets the interval duration in months.
|
||||
* @param months duration in months (based on a 30 day month)
|
||||
* @see months()
|
||||
*/
|
||||
void setMonths( double months ) { mSeconds = months * MONTHS; mValid = true; }
|
||||
|
||||
/** Returns the interval duration in weeks.
|
||||
* @see setWeeks()
|
||||
*/
|
||||
double weeks() const { return mSeconds / WEEKS; }
|
||||
|
||||
/** Sets the interval duration in weeks.
|
||||
* @param weeks duration in weeks
|
||||
* @see weeks()
|
||||
*/
|
||||
void setWeeks( double weeks ) { mSeconds = weeks * WEEKS; mValid = true; }
|
||||
|
||||
/** Returns the interval duration in days.
|
||||
* @see setDays()
|
||||
*/
|
||||
double days() const { return mSeconds / DAY; }
|
||||
|
||||
/** Sets the interval duration in days.
|
||||
* @param days duration in days
|
||||
* @see days()
|
||||
*/
|
||||
void setDays( double days ) { mSeconds = days * DAY; mValid = true; }
|
||||
|
||||
/** Returns the interval duration in hours.
|
||||
* @see setHours()
|
||||
*/
|
||||
double hours() const { return mSeconds / HOUR; }
|
||||
|
||||
/** Sets the interval duration in hours.
|
||||
* @param hours duration in hours
|
||||
* @see hours()
|
||||
*/
|
||||
void setHours( double hours ) { mSeconds = hours * HOUR; mValid = true; }
|
||||
|
||||
/** Returns the interval duration in minutes.
|
||||
* @see setMinutes()
|
||||
*/
|
||||
double minutes() const { return mSeconds / MINUTE; }
|
||||
|
||||
/** Sets the interval duration in minutes.
|
||||
* @param minutes duration in minutes
|
||||
* @see minutes()
|
||||
*/
|
||||
void setMinutes( double minutes ) { mSeconds = minutes * MINUTE; mValid = true; }
|
||||
|
||||
/** Returns the interval duration in seconds.
|
||||
* @see setSeconds()
|
||||
*/
|
||||
double seconds() const { return mSeconds; }
|
||||
|
||||
/** Sets the interval duration in seconds.
|
||||
* @param seconds duration in seconds
|
||||
* @see seconds()
|
||||
*/
|
||||
void setSeconds( double seconds ) { mSeconds = seconds; mValid = true; }
|
||||
|
||||
/** Returns true if the interval is valid.
|
||||
* @see setValid()
|
||||
*/
|
||||
bool isValid() const { return mValid; }
|
||||
|
||||
/** Sets whether the interval is valid.
|
||||
* @param valid set to true to set the interval as valid.
|
||||
* @see isValid()
|
||||
*/
|
||||
void setValid( bool valid ) { mValid = valid; }
|
||||
|
||||
bool operator==( const QgsInterval& other ) const;
|
||||
|
||||
/** Converts a string to an interval
|
||||
* @param string string to parse
|
||||
* @returns interval, or invalid interval if string could not be parsed
|
||||
*/
|
||||
static QgsInterval fromString( const QString& string );
|
||||
|
||||
private:
|
||||
|
||||
//! Duration of interval in seconds
|
||||
double mSeconds;
|
||||
|
||||
//! True if interval is valid
|
||||
bool mValid;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE( QgsInterval )
|
||||
|
||||
/** Returns the interval between two datetimes
|
||||
* @param dt1 start datetime
|
||||
* @param dt2 datetime to subtract, ie subtract dt2 from dt1
|
||||
* @note added in QGIS 2.16
|
||||
* @note not available in Python bindings
|
||||
*/
|
||||
QgsInterval CORE_EXPORT operator-( const QDateTime& dt1, const QDateTime& dt2 );
|
||||
|
||||
/** Adds an interval to a datetime
|
||||
* @param start initial datetime
|
||||
* @param interval interval to add
|
||||
* @note added in QGIS 2.16
|
||||
* @note not available in Python bindings
|
||||
*/
|
||||
QDateTime CORE_EXPORT operator+( const QDateTime& start, const QgsInterval& interval );
|
||||
|
||||
//! Debug string representation of interval
|
||||
QDebug operator<<( QDebug dbg, const QgsInterval& interval );
|
||||
\
|
||||
#endif // QGSINTERVAL_H
|
@ -28,7 +28,7 @@ email : hugo dot mercier at oslandia dot com
|
||||
#include <qgsgeometry.h>
|
||||
#include <qgsmaplayerregistry.h>
|
||||
#include <qgsproviderregistry.h>
|
||||
|
||||
#include "qgsinterval.h"
|
||||
#include <sqlite3.h>
|
||||
#include <spatialite.h>
|
||||
#include <stdio.h>
|
||||
@ -816,9 +816,9 @@ void qgisFunctionWrapper( sqlite3_context* ctxt, int nArgs, sqlite3_value** args
|
||||
qgsGeometryToSpatialiteBlob( ret.value<QgsGeometry>(), /*srid*/0, blob, size );
|
||||
sqlite3_result_blob( ctxt, blob, size, deleteGeometryBlob );
|
||||
}
|
||||
else if ( ret.canConvert<QgsExpression::Interval>() )
|
||||
else if ( ret.canConvert<QgsInterval>() )
|
||||
{
|
||||
sqlite3_result_double( ctxt, ret.value<QgsExpression::Interval>().seconds() );
|
||||
sqlite3_result_double( ctxt, ret.value<QgsInterval>().seconds() );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -734,15 +734,15 @@ class TestQgsExpression: public QObject
|
||||
|
||||
// Datetime functions
|
||||
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( QgsExpression::Interval( 34758060 ) );
|
||||
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 );
|
||||
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 ) );
|
||||
QTest::newRow( "age" ) << "age('2012-06-30','2012-06-28')" << false << QVariant::fromValue( QgsInterval( 172800 ) );
|
||||
QTest::newRow( "negative age" ) << "age('2012-06-28','2012-06-30')" << false << QVariant::fromValue( QgsInterval( -172800 ) );
|
||||
QTest::newRow( "day of week date" ) << "day_of_week(todate('2015-09-21'))" << false << QVariant( 1 );
|
||||
QTest::newRow( "day of week datetime" ) << "day_of_week(to_datetime('2015-09-20 13:01:43'))" << false << QVariant( 0 );
|
||||
QTest::newRow( "hour datetime" ) << "hour(to_datetime('2015-09-20 13:01:43'))" << false << QVariant( 13 );
|
||||
@ -909,10 +909,10 @@ class TestQgsExpression: public QObject
|
||||
break;
|
||||
case QVariant::UserType:
|
||||
{
|
||||
if ( result.userType() == qMetaTypeId<QgsExpression::Interval>() )
|
||||
if ( result.userType() == qMetaTypeId<QgsInterval>() )
|
||||
{
|
||||
QgsExpression::Interval inter = result.value<QgsExpression::Interval>();
|
||||
QgsExpression::Interval gotinter = expected.value<QgsExpression::Interval>();
|
||||
QgsInterval inter = result.value<QgsInterval>();
|
||||
QgsInterval gotinter = expected.value<QgsInterval>();
|
||||
QCOMPARE( inter.seconds(), gotinter.seconds() );
|
||||
}
|
||||
else
|
||||
|
@ -41,6 +41,7 @@ ADD_PYTHON_TEST(PyQgsGeometryAvoidIntersections test_qgsgeometry_avoid_intersect
|
||||
ADD_PYTHON_TEST(PyQgsGeometryGeneratorSymbolLayerV2 test_qgsgeometrygeneratorsymbollayerv2.py)
|
||||
ADD_PYTHON_TEST(PyQgsGeometryTest test_qgsgeometry.py)
|
||||
ADD_PYTHON_TEST(PyQgsGraduatedSymbolRendererV2 test_qgsgraduatedsymbolrendererv2.py)
|
||||
ADD_PYTHON_TEST(PyQgsInterval test_qgsinterval.py)
|
||||
ADD_PYTHON_TEST(PyQgsJSONUtils test_qgsjsonutils.py)
|
||||
ADD_PYTHON_TEST(PyQgsMapUnitScale test_qgsmapunitscale.py)
|
||||
ADD_PYTHON_TEST(PyQgsMemoryProvider test_provider_memory.py)
|
||||
|
162
tests/src/python/test_qgsinterval.py
Normal file
162
tests/src/python/test_qgsinterval.py
Normal file
@ -0,0 +1,162 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""QGIS Unit tests for QgsInterval.
|
||||
|
||||
.. note:: This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
"""
|
||||
__author__ = 'Nyall Dawson'
|
||||
__date__ = '10/05/2016'
|
||||
__copyright__ = 'Copyright 2015, The QGIS Project'
|
||||
# This will get replaced with a git SHA1 when you do a git archive
|
||||
__revision__ = '$Format:%H$'
|
||||
|
||||
import qgis # NOQA
|
||||
|
||||
from qgis.core import QgsInterval
|
||||
from qgis.testing import unittest
|
||||
from qgis.PyQt.QtCore import QDateTime, QDate, QTime
|
||||
|
||||
|
||||
class TestQgsInterval(unittest.TestCase):
|
||||
|
||||
def testIntervalConstructor(self):
|
||||
""" Test QgsInterval constructor """
|
||||
|
||||
# invalid interval
|
||||
i = QgsInterval()
|
||||
self.assertFalse(i.isValid())
|
||||
i.setValid(True)
|
||||
self.assertTrue(i.isValid())
|
||||
i.setValid(False)
|
||||
self.assertFalse(i.isValid())
|
||||
# setting a duration should make interval valid
|
||||
i.setSeconds(5)
|
||||
self.assertTrue(i.isValid())
|
||||
|
||||
# constructor with duration
|
||||
i = QgsInterval(56)
|
||||
self.assertTrue(i.isValid())
|
||||
self.assertEqual(i.seconds(), 56)
|
||||
|
||||
def testSettersGetters(self):
|
||||
# setters and getters
|
||||
i = QgsInterval()
|
||||
i.setSeconds(60)
|
||||
self.assertTrue(i.isValid())
|
||||
self.assertEqual(i.seconds(), 60.0)
|
||||
|
||||
i = QgsInterval()
|
||||
i.setMinutes(10)
|
||||
self.assertTrue(i.isValid())
|
||||
self.assertEqual(i.minutes(), 10.0)
|
||||
|
||||
i = QgsInterval()
|
||||
i.setHours(5)
|
||||
self.assertTrue(i.isValid())
|
||||
self.assertEqual(i.hours(), 5.0)
|
||||
|
||||
i = QgsInterval()
|
||||
i.setDays(70)
|
||||
self.assertTrue(i.isValid())
|
||||
self.assertEqual(i.days(), 70.0)
|
||||
|
||||
i = QgsInterval()
|
||||
i.setWeeks(9)
|
||||
self.assertTrue(i.isValid())
|
||||
self.assertEqual(i.weeks(), 9.0)
|
||||
|
||||
i = QgsInterval()
|
||||
i.setMonths(4)
|
||||
self.assertTrue(i.isValid())
|
||||
self.assertEqual(i.months(), 4.0)
|
||||
|
||||
i = QgsInterval()
|
||||
i.setYears(8)
|
||||
self.assertTrue(i.isValid())
|
||||
self.assertEqual(i.years(), 8.0)
|
||||
|
||||
def testConversions(self):
|
||||
i = QgsInterval()
|
||||
# conversions
|
||||
i.setYears(1)
|
||||
self.assertEqual(round(i.months()), 12)
|
||||
self.assertEqual(round(i.weeks()), 52)
|
||||
self.assertEqual(round(i.days()), 365)
|
||||
i.setDays(5)
|
||||
self.assertEqual(i.hours(), 5 * 24)
|
||||
self.assertEqual(i.minutes(), 5 * 24 * 60)
|
||||
self.assertEqual(i.seconds(), 5 * 24 * 60 * 60)
|
||||
|
||||
def testEquality(self):
|
||||
i1 = QgsInterval()
|
||||
i2 = QgsInterval()
|
||||
self.assertEqual(i1, i2)
|
||||
i1 = QgsInterval(5)
|
||||
self.assertNotEqual(i1, i2)
|
||||
i1.setValid(False)
|
||||
i2 = QgsInterval(5)
|
||||
self.assertNotEqual(i1, i2)
|
||||
i1 = QgsInterval(5)
|
||||
self.assertEqual(i1, i2)
|
||||
i1.setSeconds(6)
|
||||
self.assertNotEqual(i1, i2)
|
||||
|
||||
def testFromString(self):
|
||||
i = QgsInterval.fromString('1 Year 1 Month 1 Week 1 Hour 1 Minute')
|
||||
self.assertTrue(i.isValid())
|
||||
self.assertEqual(i.seconds(), 34758060)
|
||||
i = QgsInterval.fromString('1 Year, 1 Month, 1 Week, 1 Hour, 1 Minute')
|
||||
self.assertTrue(i.isValid())
|
||||
self.assertEqual(i.seconds(), 34758060)
|
||||
i = QgsInterval.fromString('1 Year; 1 Month; 1 Week; 1 Hour; 1 Minute')
|
||||
self.assertTrue(i.isValid())
|
||||
self.assertEqual(i.seconds(), 34758060)
|
||||
i = QgsInterval.fromString('1 Year. 1 Month. 1 Week. 1 Hour. 1 Minute.')
|
||||
self.assertTrue(i.isValid())
|
||||
self.assertEqual(i.seconds(), 34758060)
|
||||
i = QgsInterval.fromString('2 Years')
|
||||
self.assertTrue(i.isValid())
|
||||
self.assertEqual(i.years(), 2)
|
||||
i = QgsInterval.fromString('30 month')
|
||||
self.assertTrue(i.isValid())
|
||||
self.assertEqual(i.months(), 30)
|
||||
i = QgsInterval.fromString(' 40 MONTHS ')
|
||||
self.assertTrue(i.isValid())
|
||||
self.assertEqual(i.months(), 40)
|
||||
i = QgsInterval.fromString('2.5 weeks')
|
||||
self.assertTrue(i.isValid())
|
||||
self.assertEqual(i.weeks(), 2.5)
|
||||
i = QgsInterval.fromString('2.5 WEEK')
|
||||
self.assertTrue(i.isValid())
|
||||
self.assertEqual(i.weeks(), 2.5)
|
||||
i = QgsInterval.fromString('1 Day')
|
||||
self.assertTrue(i.isValid())
|
||||
self.assertEqual(i.seconds(), 24 * 60 * 60)
|
||||
i = QgsInterval.fromString('2 dAys')
|
||||
self.assertTrue(i.isValid())
|
||||
self.assertEqual(i.seconds(), 48 * 60 * 60)
|
||||
i = QgsInterval.fromString('1 hours')
|
||||
self.assertTrue(i.isValid())
|
||||
self.assertEqual(i.hours(), 1)
|
||||
i = QgsInterval.fromString('1.7 HoURS ')
|
||||
self.assertTrue(i.isValid())
|
||||
self.assertEqual(i.hours(), 1.7)
|
||||
i = QgsInterval.fromString('2 minutes')
|
||||
self.assertTrue(i.isValid())
|
||||
self.assertEqual(i.minutes(), 2)
|
||||
i = QgsInterval.fromString('123 MiNuTe ')
|
||||
self.assertTrue(i.isValid())
|
||||
self.assertEqual(i.minutes(), 123)
|
||||
i = QgsInterval.fromString('5 Seconds')
|
||||
self.assertTrue(i.isValid())
|
||||
self.assertEqual(i.seconds(), 5)
|
||||
i = QgsInterval.fromString('5 second')
|
||||
self.assertTrue(i.isValid())
|
||||
self.assertEqual(i.seconds(), 5)
|
||||
i = QgsInterval.fromString('bad')
|
||||
self.assertFalse(i.isValid())
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
Loading…
x
Reference in New Issue
Block a user