Skip to content

Commit

Permalink
De-duplicate code
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Mar 25, 2021
1 parent 2cf7a56 commit 41053cc
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 226 deletions.
1 change: 1 addition & 0 deletions python/core/auto_generated/qgstemporalutils.sip.in
Expand Up @@ -119,6 +119,7 @@ Calculates a complete list of datetimes between ``start`` and ``end``, using the
.. versionadded:: 3.20
%End


static QList< QDateTime > calculateDateTimesFromISO8601( const QString &string, bool &ok /Out/, bool &maxValuesExceeded /Out/, int maxValues = -1 );
%Docstring
Calculates a complete list of datetimes from a ISO8601 ``string`` containing a duration (eg "2021-03-23T00:00:00Z/2021-03-24T12:00:00Z/PT12H").
Expand Down
86 changes: 86 additions & 0 deletions src/core/qgstemporalutils.cpp
Expand Up @@ -28,6 +28,8 @@
#include "qgsmaprenderercustompainterjob.h"
#include "qgsexpressioncontextutils.h"

#include <QRegularExpression>

QgsDateTimeRange QgsTemporalUtils::calculateTemporalRangeForProject( QgsProject *project )
{
QMap<QString, QgsMapLayer *> mapLayers = project->mapLayers();
Expand Down Expand Up @@ -222,7 +224,11 @@ QList<QDateTime> QgsTemporalUtils::calculateDateTimesUsingDuration( const QDateT
ok = false;
return {};
}
return calculateDateTimesUsingDuration( start, end, timeDuration, maxValuesExceeded, maxValues );
}

QList<QDateTime> QgsTemporalUtils::calculateDateTimesUsingDuration( const QDateTime &start, const QDateTime &end, const QgsTimeDuration &timeDuration, bool &maxValuesExceeded, int maxValues )
{
QList<QDateTime> res;
QDateTime current = start;
maxValuesExceeded = false;
Expand Down Expand Up @@ -272,6 +278,86 @@ QList<QDateTime> QgsTemporalUtils::calculateDateTimesFromISO8601( const QString
// QgsTimeDuration
//

QString QgsTimeDuration::toString() const
{
QString text( "P" );

if ( years )
{
text.append( QString::number( years ) );
text.append( 'Y' );
}
if ( months )
{
text.append( QString::number( months ) );
text.append( 'M' );
}
if ( days )
{
text.append( QString::number( days ) );
text.append( 'D' );
}

if ( hours )
{
if ( !text.contains( 'T' ) )
text.append( 'T' );
text.append( QString::number( hours ) );
text.append( 'H' );
}
if ( minutes )
{
if ( !text.contains( 'T' ) )
text.append( 'T' );
text.append( QString::number( minutes ) );
text.append( 'M' );
}
if ( seconds )
{
if ( !text.contains( 'T' ) )
text.append( 'T' );
text.append( QString::number( seconds ) );
text.append( 'S' );
}
return text;
}

long long QgsTimeDuration::toSeconds() const
{
long long secs = 0.0;

if ( years )
secs += years * QgsInterval::YEARS;
if ( months )
secs += months * QgsInterval::MONTHS;
if ( days )
secs += days * QgsInterval::DAY;
if ( hours )
secs += hours * QgsInterval::HOUR;
if ( minutes )
secs += minutes * QgsInterval::MINUTE;
if ( seconds )
secs += seconds;

return secs;
}

QDateTime QgsTimeDuration::addToDateTime( const QDateTime &dateTime )
{
QDateTime resultDateTime = dateTime;

if ( years )
resultDateTime = resultDateTime.addYears( years );
if ( months )
resultDateTime = resultDateTime.addMonths( months );
if ( weeks || days )
resultDateTime = resultDateTime.addDays( weeks * 7 + days );
if ( hours || minutes || seconds )
resultDateTime = resultDateTime.addSecs( hours * 60LL * 60 + minutes * 60 + seconds );

return resultDateTime;
}

QgsTimeDuration QgsTimeDuration::fromString( const QString &string, bool &ok )
{
ok = false;
Expand Down
55 changes: 55 additions & 0 deletions src/core/qgstemporalutils.h
Expand Up @@ -56,6 +56,45 @@ class CORE_EXPORT QgsTimeDuration
//! Seconds
double seconds = 0;

/**
* Returns TRUE if the duration is null, i.e. an empty duration.
*/
bool isNull() const
{
return !years && !months && !days &&
!hours && !minutes && !seconds;
}

bool operator==( const QgsTimeDuration &other ) const
{
return years == other.years && months == other.months &&
days == other.days && hours == other.hours &&
minutes == other.minutes && seconds == other.seconds;
}

bool operator!=( const QgsTimeDuration &other ) const
{
return !( *this == other );
}

/**
* Converts the duration to an ISO8601 duration string.
*/
QString toString() const;

/**
* Returns the total duration in seconds.
*
* \warning If the duration contains year or month intervals then the returned
* value is approximate only, due to the variable length of these intervals.
*/
long long toSeconds() const;

/**
* Adds this duration to a starting \a dateTime value.
*/
QDateTime addToDateTime( const QDateTime &dateTime );

/**
* Creates a QgsTimeDuration from a \a string value.
*/
Expand Down Expand Up @@ -179,6 +218,22 @@ class CORE_EXPORT QgsTemporalUtils
*/
static QList< QDateTime > calculateDateTimesUsingDuration( const QDateTime &start, const QDateTime &end, const QString &duration, bool &ok SIP_OUT, bool &maxValuesExceeded SIP_OUT, int maxValues = -1 );

#ifndef SIP_RUN

/**
* Calculates a complete list of datetimes between \a start and \a end, using the specified ISO8601 \a duration string (eg "PT12H").
* \param start start date time
* \param end end date time
* \param duration ISO8601 duration
* \param maxValuesExceeded will be set to TRUE if the maximum number of values to return was exceeded
* \param maxValues maximum number of values to return, or -1 to return all values
* \returns calculated list of date times
* \note Not available in Python bindings
* \since QGIS 3.20
*/
static QList< QDateTime > calculateDateTimesUsingDuration( const QDateTime &start, const QDateTime &end, const QgsTimeDuration &duration, bool &maxValuesExceeded SIP_OUT, int maxValues = -1 );
#endif

/**
* Calculates a complete list of datetimes from a ISO8601 \a string containing a duration (eg "2021-03-23T00:00:00Z/2021-03-24T12:00:00Z/PT12H").
* \param string ISO8601 compatible string
Expand Down
119 changes: 12 additions & 107 deletions src/providers/wms/qgswmscapabilities.cpp
Expand Up @@ -109,11 +109,10 @@ bool QgsWmsSettings::parseUri( const QString &uriString )
const QDateTime begin = extent.dates.dateTimes.first();
const QDateTime end = extent.dates.dateTimes.last();

bool ok = false;
bool maxValuesExceeded = false;
const QList< QDateTime > dates = QgsTemporalUtils::calculateDateTimesFromISO8601( extent.originalString, ok, maxValuesExceeded );
if ( ok )
if ( !extent.resolution.isNull() )
{
bool maxValuesExceeded = false;
const QList< QDateTime > dates = QgsTemporalUtils::calculateDateTimesUsingDuration( begin, end, extent.resolution, maxValuesExceeded );
for ( const QDateTime &dt : dates )
mAllRanges.append( QgsDateTimeRange( dt, dt ) );
}
Expand All @@ -123,7 +122,7 @@ bool QgsWmsSettings::parseUri( const QString &uriString )
}
}

if ( uri.param( QStringLiteral( "referenceTimeDimensionExtent" ) ) != QString() )
if ( !uri.param( QStringLiteral( "referenceTimeDimensionExtent" ) ).isEmpty() )
{
QString referenceExtent = uri.param( QStringLiteral( "referenceTimeDimensionExtent" ) );

Expand Down Expand Up @@ -259,7 +258,7 @@ QgsWmstDimensionExtent QgsWmsSettings::parseTemporalExtent( const QString &exten
{
const QStringList itemParts = item.split( '/' );

QgsWmstResolution itemResolution;
QgsTimeDuration itemResolution;
QgsWmstDates itemDatesList;

for ( const QString &itemPart : itemParts )
Expand All @@ -276,11 +275,11 @@ QgsWmstDimensionExtent QgsWmsSettings::parseTemporalExtent( const QString &exten
}
}

dimensionExtent.datesResolutionList.append( QgsWmstExtentPair( itemDatesList, itemResolution, item ) );
dimensionExtent.datesResolutionList.append( QgsWmstExtentPair( itemDatesList, itemResolution ) );
}
else
{
QgsWmstResolution resolution;
QgsTimeDuration resolution;
QgsWmstDates datesList;
if ( item.startsWith( 'P' ) )
{
Expand All @@ -291,7 +290,7 @@ QgsWmstDimensionExtent QgsWmsSettings::parseTemporalExtent( const QString &exten
datesList.dateTimes.append( parseWmstDateTimes( item ) );
}

dimensionExtent.datesResolutionList.append( QgsWmstExtentPair( datesList, resolution, item ) );
dimensionExtent.datesResolutionList.append( QgsWmstExtentPair( datesList, resolution ) );
}
}

Expand All @@ -308,26 +307,6 @@ QgsWmstDimensionExtent QgsWmsSettings::timeDimensionExtent() const
return mTimeDimensionExtent;
}

QDateTime QgsWmsSettings::addTime( const QDateTime &dateTime, const QgsWmstResolution &resolution )
{
QDateTime resultDateTime = QDateTime( dateTime );

if ( resolution.year != -1 )
resultDateTime = resultDateTime.addYears( resolution.year );
if ( resolution.month != -1 )
resultDateTime = resultDateTime.addMonths( resolution.month );
if ( resolution.day != -1 )
resultDateTime = resultDateTime.addDays( resolution.day );
if ( resolution.hour != -1 )
resultDateTime = resultDateTime.addSecs( resolution.hour * 60 * 60 );
if ( resolution.minutes != -1 )
resultDateTime = resultDateTime.addSecs( resolution.minutes * 60 );
if ( resolution.seconds != -1 )
resultDateTime = resultDateTime.addSecs( resolution.seconds );

return resultDateTime;
}

QDateTime QgsWmsSettings::findLeastClosestDateTime( const QDateTime &dateTime, bool dateOnly ) const
{
QDateTime closest = dateTime;
Expand Down Expand Up @@ -366,7 +345,7 @@ QDateTime QgsWmsSettings::findLeastClosestDateTime( const QDateTime &dateTime, b
if ( seconds == endSeconds )
break;

long long resolutionSeconds = pair.resolution.interval();
long long resolutionSeconds = pair.resolution.toSeconds();

if ( resolutionSeconds <= 0 )
continue;
Expand All @@ -380,84 +359,10 @@ QDateTime QgsWmsSettings::findLeastClosestDateTime( const QDateTime &dateTime, b
return closest;
}

QgsWmstResolution QgsWmsSettings::parseWmstResolution( const QString &itemText )
QgsTimeDuration QgsWmsSettings::parseWmstResolution( const QString &itemText )
{
QString item = itemText;
QgsWmstResolution resolution;
bool found = false;

for ( char datesSymbol : { 'Y', 'M', 'D' } )
{
QString number = item.left( item.indexOf( datesSymbol ) );
int resolutionValue = number.remove( 'P' ).toInt();

if ( datesSymbol == 'Y' && item.contains( 'Y' ) )
{
resolution.year = resolutionValue;
found = true;
}
if ( datesSymbol == 'M' && item.contains( 'M' ) )
{
// Symbol M is used to both represent either month or minutes
// The check below is for determining whether it means month or minutes
if ( item.contains( 'T' ) &&
item.indexOf( 'T' ) < item.indexOf( 'M' ) )
continue;
resolution.month = resolutionValue;
found = true;
}
if ( datesSymbol == 'D' && item.contains( 'D' ) )
{
resolution.day = resolutionValue;
found = true;
}

if ( found )
{
int symbolIndex = item.indexOf( datesSymbol );
item.remove( symbolIndex, 1 );
item.remove( symbolIndex - number.length(),
number.length() );
found = false;
}
}
if ( !item.contains( 'T' ) )
return resolution;
else
item.remove( 'T' );

bool foundTime = false;

for ( char timeSymbol : { 'H', 'M', 'S' } )
{
QString number = item.left( item.indexOf( timeSymbol ) );
int resolutionValue = number.remove( 'P' ).toInt();

if ( timeSymbol == 'H' && item.contains( 'H' ) )
{
resolution.hour = resolutionValue;
foundTime = true;
}
if ( timeSymbol == 'M' && item.contains( 'M' ) )
{
resolution.minutes = resolutionValue;
foundTime = true;
}
if ( timeSymbol == 'S' && item.contains( 'S' ) )
{
resolution.seconds = resolutionValue;
foundTime = true;
}

if ( foundTime )
{
int symbolIndex = item.indexOf( timeSymbol );
item.remove( symbolIndex, 1 );
item.remove( symbolIndex - number.length(),
number.length() );
foundTime = false;
}
}
bool ok = false;
QgsTimeDuration resolution = QgsTimeDuration::fromString( itemText, ok );
return resolution;
}

Expand Down

0 comments on commit 41053cc

Please sign in to comment.