def testFixedRangeMode(self):
        props = QgsVectorLayerTemporalProperties(enabled=True)
        props.setMode(QgsVectorLayerTemporalProperties.ModeFixedTemporalRange)
        props.setFixedTemporalRange(QgsDateTimeRange(QDateTime(QDate(2019, 3, 4), QTime(11, 12, 13)), QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10))))

        self.assertTrue(props.isVisibleInTemporalRange(QgsDateTimeRange(QDateTime(QDate(2019, 3, 4), QTime(11, 12, 13)), QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)))))
        self.assertTrue(props.isVisibleInTemporalRange(QgsDateTimeRange(QDateTime(QDate(2019, 1, 4), QTime(11, 12, 13)), QDateTime(QDate(2019, 5, 6), QTime(8, 9, 10)))))
        self.assertTrue(props.isVisibleInTemporalRange(QgsDateTimeRange(QDateTime(QDate(2020, 3, 4), QTime(11, 12, 13)), QDateTime(QDate(2019, 9, 6), QTime(8, 9, 10)))))
        self.assertFalse(props.isVisibleInTemporalRange(QgsDateTimeRange(QDateTime(QDate(2120, 3, 4), QTime(11, 12, 13)), QDateTime(QDate(2121, 9, 6), QTime(8, 9, 10)))))
        self.assertFalse(props.isVisibleInTemporalRange(QgsDateTimeRange(QDateTime(QDate(1920, 3, 4), QTime(11, 12, 13)), QDateTime(QDate(1921, 9, 6), QTime(8, 9, 10)))))

        layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer&field=start_field:datetime", "test", "memory")
        range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4), QTime(11, 12, 13)), QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)))
        # ALWAYS must be empty for ModeFixedTemporalRange
        self.assertFalse(props.createFilterString(layer, range))
示例#2
0
    def testModeFromProvider(self):
        caps = QgsVectorDataProviderTemporalCapabilities()
        props = QgsVectorLayerTemporalProperties()
        props.setDefaultsFromDataProviderTemporalCapabilities(caps)
        self.assertFalse(props.isActive())

        caps.setHasTemporalCapabilities(True)
        caps.setAvailableTemporalRange(
            QgsDateTimeRange(QDateTime(2006, 3, 11, 0, 13, 20),
                             QDateTime(2017, 2, 14, 1, 33, 20)))
        props.setDefaultsFromDataProviderTemporalCapabilities(caps)
        self.assertTrue(props.isActive())
        self.assertFalse(props.startField())
        self.assertFalse(props.endField())
        self.assertEqual(
            props.mode(),
            QgsVectorLayerTemporalProperties.ModeFixedTemporalRange)
        self.assertEqual(props.fixedTemporalRange().begin(),
                         QDateTime(2006, 3, 11, 0, 13, 20))
        self.assertEqual(props.fixedTemporalRange().end(),
                         QDateTime(2017, 2, 14, 1, 33, 20))

        caps.setStartField('start_field')
        caps.setMode(QgsVectorDataProviderTemporalCapabilities.
                     ProviderStoresFeatureDateTimeInstantInField)
        props.setDefaultsFromDataProviderTemporalCapabilities(caps)
        self.assertTrue(props.isActive())
        self.assertEqual(props.startField(), 'start_field')
        self.assertFalse(props.endField())
        self.assertEqual(
            props.mode(), QgsVectorLayerTemporalProperties.
            ModeFeatureDateTimeInstantFromField)

        caps.setEndField('end_field')
        caps.setMode(QgsVectorDataProviderTemporalCapabilities.
                     ProviderStoresFeatureDateTimeStartAndEndInSeparateFields)
        props.setDefaultsFromDataProviderTemporalCapabilities(caps)
        self.assertTrue(props.isActive())
        self.assertEqual(props.startField(), 'start_field')
        self.assertEqual(props.endField(), 'end_field')
        self.assertEqual(
            props.mode(), QgsVectorLayerTemporalProperties.
            ModeFeatureDateTimeStartAndEndFromFields)
示例#3
0
    def testExpressionMode(self):
        layer = QgsVectorLayer(
            "Point?field=fldtxt:string&field=fldint:integer&field=start_field:datetime&field=end_field:datetime",
            "test", "memory")
        self.assertTrue(layer.isValid())
        self.assertEqual(layer.fields()[2].type(), QVariant.DateTime)
        self.assertEqual(layer.fields()[3].type(), QVariant.DateTime)

        range = QgsDateTimeRange(
            QDateTime(QDate(2019, 3, 4), QTime(11, 12, 13)),
            QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)))

        props = QgsVectorLayerTemporalProperties(enabled=False)
        props.setMode(QgsVectorLayerTemporalProperties.
                      ModeFeatureDateTimeStartAndEndFromExpressions)
        props.setStartExpression(
            'to_datetime("my string field",  \'yyyy MM dd hh::mm:ss\')"')
        props.setEndExpression(
            'to_datetime("my end field",  \'yyyy MM dd hh::mm:ss\')"')
        self.assertFalse(props.createFilterString(layer, range))

        props.setIsActive(True)
        self.assertEqual(
            props.createFilterString(layer, range),
            '((to_datetime("my string field",  \'yyyy MM dd hh::mm:ss\')") <= make_datetime(2020,5,6,8,9,10)) AND ((to_datetime("my end field",  \'yyyy MM dd hh::mm:ss\')") >= make_datetime(2019,3,4,11,12,13))'
        )

        range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4),
                                           QTime(11, 12, 13)),
                                 QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)),
                                 includeBeginning=False)
        self.assertEqual(
            props.createFilterString(layer, range),
            '((to_datetime("my string field",  \'yyyy MM dd hh::mm:ss\')") <= make_datetime(2020,5,6,8,9,10)) AND ((to_datetime("my end field",  \'yyyy MM dd hh::mm:ss\')") > make_datetime(2019,3,4,11,12,13))'
        )

        range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4),
                                           QTime(11, 12, 13)),
                                 QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)),
                                 includeEnd=False)
        self.assertEqual(
            props.createFilterString(layer, range),
            '((to_datetime("my string field",  \'yyyy MM dd hh::mm:ss\')") < make_datetime(2020,5,6,8,9,10)) AND ((to_datetime("my end field",  \'yyyy MM dd hh::mm:ss\')") >= make_datetime(2019,3,4,11,12,13))'
        )

        props.setEndExpression('')
        self.assertEqual(
            props.createFilterString(layer, range),
            '(to_datetime("my string field",  \'yyyy MM dd hh::mm:ss\')") <= make_datetime(2020,5,6,8,9,10)'
        )

        range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4),
                                           QTime(11, 12, 13)),
                                 QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)),
                                 includeBeginning=False)
        self.assertEqual(
            props.createFilterString(layer, range),
            '(to_datetime("my string field",  \'yyyy MM dd hh::mm:ss\')") < make_datetime(2020,5,6,8,9,10)'
        )

        range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4),
                                           QTime(11, 12, 13)),
                                 QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)),
                                 includeEnd=False)
        self.assertEqual(
            props.createFilterString(layer, range),
            '(to_datetime("my string field",  \'yyyy MM dd hh::mm:ss\')") <= make_datetime(2020,5,6,8,9,10)'
        )

        props.setStartExpression('')
        props.setEndExpression(
            'to_datetime("my end field",  \'yyyy MM dd hh::mm:ss\')"')
        self.assertEqual(
            props.createFilterString(layer, range),
            '(to_datetime("my end field",  \'yyyy MM dd hh::mm:ss\')") >= make_datetime(2019,3,4,11,12,13)'
        )

        range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4),
                                           QTime(11, 12, 13)),
                                 QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)),
                                 includeBeginning=False)
        self.assertEqual(
            props.createFilterString(layer, range),
            '(to_datetime("my end field",  \'yyyy MM dd hh::mm:ss\')") > make_datetime(2019,3,4,11,12,13)'
        )

        range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4),
                                           QTime(11, 12, 13)),
                                 QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)),
                                 includeEnd=False)
        self.assertEqual(
            props.createFilterString(layer, range),
            '(to_datetime("my end field",  \'yyyy MM dd hh::mm:ss\')") >= make_datetime(2019,3,4,11,12,13)'
        )
示例#4
0
    def testStartAndDurationMode(self):
        layer = QgsVectorLayer(
            "Point?field=fldtxt:string&field=fldint:integer&field=start_field:datetime&field=duration:double",
            "test", "memory")
        self.assertTrue(layer.isValid())
        self.assertEqual(layer.fields()[2].type(), QVariant.DateTime)
        self.assertEqual(layer.fields()[3].type(), QVariant.Double)

        range = QgsDateTimeRange(
            QDateTime(QDate(2019, 3, 4), QTime(11, 12, 13)),
            QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)))

        props = QgsVectorLayerTemporalProperties(enabled=False)
        props.setMode(QgsVectorLayerTemporalProperties.
                      ModeFeatureDateTimeStartAndDurationFromFields)
        props.setStartField('start_field')
        props.setDurationField('duration')
        props.setDurationUnits(QgsUnitTypes.TemporalMilliseconds)
        self.assertFalse(props.createFilterString(layer, range))

        props.setIsActive(True)
        self.assertEqual(
            props.createFilterString(layer, range),
            '("start_field" <= make_datetime(2020,5,6,8,9,10) OR "start_field" IS NULL) AND (("start_field" + make_interval(0,0,0,0,0,0,"duration"/1000) >= make_datetime(2019,3,4,11,12,13)) OR "duration" IS NULL)'
        )

        props.setDurationUnits(QgsUnitTypes.TemporalSeconds)
        self.assertEqual(
            props.createFilterString(layer, range),
            '("start_field" <= make_datetime(2020,5,6,8,9,10) OR "start_field" IS NULL) AND (("start_field" + make_interval(0,0,0,0,0,0,"duration") >= make_datetime(2019,3,4,11,12,13)) OR "duration" IS NULL)'
        )

        props.setDurationUnits(QgsUnitTypes.TemporalMinutes)
        self.assertEqual(
            props.createFilterString(layer, range),
            '("start_field" <= make_datetime(2020,5,6,8,9,10) OR "start_field" IS NULL) AND (("start_field" + make_interval(0,0,0,0,0,"duration",0) >= make_datetime(2019,3,4,11,12,13)) OR "duration" IS NULL)'
        )

        props.setDurationUnits(QgsUnitTypes.TemporalHours)
        self.assertEqual(
            props.createFilterString(layer, range),
            '("start_field" <= make_datetime(2020,5,6,8,9,10) OR "start_field" IS NULL) AND (("start_field" + make_interval(0,0,0,0,"duration",0,0) >= make_datetime(2019,3,4,11,12,13)) OR "duration" IS NULL)'
        )

        props.setDurationUnits(QgsUnitTypes.TemporalDays)
        self.assertEqual(
            props.createFilterString(layer, range),
            '("start_field" <= make_datetime(2020,5,6,8,9,10) OR "start_field" IS NULL) AND (("start_field" + make_interval(0,0,0,"duration",0,0,0) >= make_datetime(2019,3,4,11,12,13)) OR "duration" IS NULL)'
        )

        props.setDurationUnits(QgsUnitTypes.TemporalWeeks)
        self.assertEqual(
            props.createFilterString(layer, range),
            '("start_field" <= make_datetime(2020,5,6,8,9,10) OR "start_field" IS NULL) AND (("start_field" + make_interval(0,0,"duration",0,0,0,0) >= make_datetime(2019,3,4,11,12,13)) OR "duration" IS NULL)'
        )

        props.setDurationUnits(QgsUnitTypes.TemporalMonths)
        self.assertEqual(
            props.createFilterString(layer, range),
            '("start_field" <= make_datetime(2020,5,6,8,9,10) OR "start_field" IS NULL) AND (("start_field" + make_interval(0,"duration",0,0,0,0,0) >= make_datetime(2019,3,4,11,12,13)) OR "duration" IS NULL)'
        )

        props.setDurationUnits(QgsUnitTypes.TemporalYears)
        self.assertEqual(
            props.createFilterString(layer, range),
            '("start_field" <= make_datetime(2020,5,6,8,9,10) OR "start_field" IS NULL) AND (("start_field" + make_interval("duration",0,0,0,0,0,0) >= make_datetime(2019,3,4,11,12,13)) OR "duration" IS NULL)'
        )

        props.setDurationUnits(QgsUnitTypes.TemporalDecades)
        self.assertEqual(
            props.createFilterString(layer, range),
            '("start_field" <= make_datetime(2020,5,6,8,9,10) OR "start_field" IS NULL) AND (("start_field" + make_interval(10 * "duration",0,0,0,0,0,0) >= make_datetime(2019,3,4,11,12,13)) OR "duration" IS NULL)'
        )

        props.setDurationUnits(QgsUnitTypes.TemporalCenturies)
        self.assertEqual(
            props.createFilterString(layer, range),
            '("start_field" <= make_datetime(2020,5,6,8,9,10) OR "start_field" IS NULL) AND (("start_field" + make_interval(100 * "duration",0,0,0,0,0,0) >= make_datetime(2019,3,4,11,12,13)) OR "duration" IS NULL)'
        )
示例#5
0
    def testDualFieldMode(self):
        layer = QgsVectorLayer(
            "Point?field=fldtxt:string&field=fldint:integer&field=start_field:datetime&field=end_field:datetime",
            "test", "memory")
        self.assertTrue(layer.isValid())
        self.assertEqual(layer.fields()[2].type(), QVariant.DateTime)
        self.assertEqual(layer.fields()[3].type(), QVariant.DateTime)

        range = QgsDateTimeRange(
            QDateTime(QDate(2019, 3, 4), QTime(11, 12, 13)),
            QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)))

        props = QgsVectorLayerTemporalProperties(enabled=False)
        props.setMode(QgsVectorLayerTemporalProperties.
                      ModeFeatureDateTimeStartAndEndFromFields)
        props.setStartField('start_field')
        props.setEndField('end_field')
        self.assertFalse(props.createFilterString(layer, range))

        props.setIsActive(True)
        self.assertEqual(
            props.createFilterString(layer, range),
            '("start_field" <= make_datetime(2020,5,6,8,9,10) OR "start_field" IS NULL) AND ("end_field" >= make_datetime(2019,3,4,11,12,13) OR "end_field" IS NULL)'
        )

        range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4),
                                           QTime(11, 12, 13)),
                                 QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)),
                                 includeBeginning=False)
        self.assertEqual(
            props.createFilterString(layer, range),
            '("start_field" <= make_datetime(2020,5,6,8,9,10) OR "start_field" IS NULL) AND ("end_field" > make_datetime(2019,3,4,11,12,13) OR "end_field" IS NULL)'
        )

        range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4),
                                           QTime(11, 12, 13)),
                                 QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)),
                                 includeEnd=False)
        self.assertEqual(
            props.createFilterString(layer, range),
            '("start_field" < make_datetime(2020,5,6,8,9,10) OR "start_field" IS NULL) AND ("end_field" >= make_datetime(2019,3,4,11,12,13) OR "end_field" IS NULL)'
        )

        props.setEndField('')
        self.assertEqual(
            props.createFilterString(layer, range),
            '"start_field" <= make_datetime(2020,5,6,8,9,10) OR "start_field" IS NULL'
        )

        range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4),
                                           QTime(11, 12, 13)),
                                 QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)),
                                 includeBeginning=False)
        self.assertEqual(
            props.createFilterString(layer, range),
            '"start_field" < make_datetime(2020,5,6,8,9,10) OR "start_field" IS NULL'
        )

        range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4),
                                           QTime(11, 12, 13)),
                                 QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)),
                                 includeEnd=False)
        self.assertEqual(
            props.createFilterString(layer, range),
            '"start_field" <= make_datetime(2020,5,6,8,9,10) OR "start_field" IS NULL'
        )

        props.setStartField('')
        props.setEndField('end_field')
        self.assertEqual(
            props.createFilterString(layer, range),
            '"end_field" >= make_datetime(2019,3,4,11,12,13) OR "end_field" IS NULL'
        )

        range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4),
                                           QTime(11, 12, 13)),
                                 QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)),
                                 includeBeginning=False)
        self.assertEqual(
            props.createFilterString(layer, range),
            '"end_field" > make_datetime(2019,3,4,11,12,13) OR "end_field" IS NULL'
        )

        range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4),
                                           QTime(11, 12, 13)),
                                 QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)),
                                 includeEnd=False)
        self.assertEqual(
            props.createFilterString(layer, range),
            '"end_field" >= make_datetime(2019,3,4,11,12,13) OR "end_field" IS NULL'
        )
示例#6
0
    def testReadWrite(self):
        props = QgsVectorLayerTemporalProperties()
        props.setMode(QgsVectorLayerTemporalProperties.
                      ModeFeatureDateTimeInstantFromField)
        props.setFixedTemporalRange(
            QgsDateTimeRange(QDateTime(QDate(2019, 3, 4), QTime(11, 12, 13)),
                             QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10))))
        props.setStartField('start')
        props.setEndField('end')
        props.setDurationField('duration')
        props.setDurationUnits(QgsUnitTypes.TemporalWeeks)
        props.setFixedDuration(5.6)
        props.setAccumulateFeatures(True)
        props.setStartExpression('start exp')
        props.setEndExpression('end exp')

        # save to xml
        doc = QDomDocument("testdoc")
        elem = doc.createElement('test')
        elem = props.writeXml(elem, doc, QgsReadWriteContext())

        # restore from xml
        props2 = QgsVectorLayerTemporalProperties()
        self.assertTrue(props2.readXml(elem, QgsReadWriteContext()))

        self.assertEqual(props2.mode(), props.mode())
        self.assertEqual(props2.fixedTemporalRange(),
                         props.fixedTemporalRange())
        self.assertEqual(props2.startField(), props.startField())
        self.assertEqual(props2.endField(), props.endField())
        self.assertEqual(props2.durationField(), props.durationField())
        self.assertEqual(props2.durationUnits(), props.durationUnits())
        self.assertEqual(props2.fixedDuration(), props.fixedDuration())
        self.assertEqual(props2.accumulateFeatures(),
                         props.accumulateFeatures())
        self.assertEqual(props2.startExpression(), props.startExpression())
        self.assertEqual(props2.endExpression(), props.endExpression())
示例#7
0
    def testSingleFieldMode(self):
        layer = QgsVectorLayer(
            "Point?field=fldtxt:string&field=fldint:integer&field=start_field:datetime",
            "test", "memory")
        self.assertTrue(layer.isValid())
        self.assertEqual(layer.fields()[2].type(), QVariant.DateTime)

        range = QgsDateTimeRange(
            QDateTime(QDate(2019, 3, 4), QTime(11, 12, 13)),
            QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)))

        props = QgsVectorLayerTemporalProperties(enabled=False)
        props.setMode(QgsVectorLayerTemporalProperties.
                      ModeFeatureDateTimeInstantFromField)
        props.setStartField('start_field')
        self.assertFalse(props.createFilterString(layer, range))

        props.setIsActive(True)
        self.assertEqual(
            props.createFilterString(layer, range),
            '("start_field" >= make_datetime(2019,3,4,11,12,13) AND "start_field" <= make_datetime(2020,5,6,8,9,10)) OR "start_field" IS NULL'
        )

        range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4),
                                           QTime(11, 12, 13)),
                                 QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)),
                                 includeBeginning=False)
        self.assertEqual(
            props.createFilterString(layer, range),
            '("start_field" > make_datetime(2019,3,4,11,12,13) AND "start_field" <= make_datetime(2020,5,6,8,9,10)) OR "start_field" IS NULL'
        )

        range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4),
                                           QTime(11, 12, 13)),
                                 QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)),
                                 includeEnd=False)
        self.assertEqual(
            props.createFilterString(layer, range),
            '("start_field" >= make_datetime(2019,3,4,11,12,13) AND "start_field" < make_datetime(2020,5,6,8,9,10)) OR "start_field" IS NULL'
        )

        # with fixed duration
        props.setFixedDuration(3)
        props.setDurationUnits(QgsUnitTypes.TemporalDays)
        range = QgsDateTimeRange(
            QDateTime(QDate(2019, 3, 4), QTime(11, 12, 13)),
            QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)))
        self.assertEqual(
            props.createFilterString(layer, range),
            '("start_field" >= make_datetime(2019,3,1,11,12,13) AND "start_field" <= make_datetime(2020,5,6,8,9,10)) OR "start_field" IS NULL'
        )

        range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4),
                                           QTime(11, 12, 13)),
                                 QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)),
                                 includeBeginning=False)
        self.assertEqual(
            props.createFilterString(layer, range),
            '("start_field" > make_datetime(2019,3,1,11,12,13) AND "start_field" <= make_datetime(2020,5,6,8,9,10)) OR "start_field" IS NULL'
        )

        range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4),
                                           QTime(11, 12, 13)),
                                 QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)),
                                 includeEnd=False)
        self.assertEqual(
            props.createFilterString(layer, range),
            '("start_field" >= make_datetime(2019,3,1,11,12,13) AND "start_field" < make_datetime(2020,5,6,8,9,10)) OR "start_field" IS NULL'
        )

        props.setDurationUnits(QgsUnitTypes.TemporalMinutes)
        range = QgsDateTimeRange(
            QDateTime(QDate(2019, 3, 4), QTime(11, 12, 13)),
            QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)))
        self.assertEqual(
            props.createFilterString(layer, range),
            '("start_field" >= make_datetime(2019,3,4,11,9,13) AND "start_field" <= make_datetime(2020,5,6,8,9,10)) OR "start_field" IS NULL'
        )

        # accumulate mode
        props.setAccumulateFeatures(True)
        range = QgsDateTimeRange(
            QDateTime(QDate(2019, 3, 4), QTime(11, 12, 13)),
            QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)))
        self.assertEqual(
            props.createFilterString(layer, range),
            '("start_field" <= make_datetime(2020,5,6,8,9,10)) OR "start_field" IS NULL'
        )

        range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4),
                                           QTime(11, 12, 13)),
                                 QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)),
                                 includeBeginning=False)
        self.assertEqual(
            props.createFilterString(layer, range),
            '("start_field" <= make_datetime(2020,5,6,8,9,10)) OR "start_field" IS NULL'
        )

        range = QgsDateTimeRange(QDateTime(QDate(2019, 3, 4),
                                           QTime(11, 12, 13)),
                                 QDateTime(QDate(2020, 5, 6), QTime(8, 9, 10)),
                                 includeEnd=False)
        self.assertEqual(
            props.createFilterString(layer, range),
            '("start_field" < make_datetime(2020,5,6,8,9,10)) OR "start_field" IS NULL'
        )