7

I have a datetime string with microsecond. I use the following script to get a QDateTime object and add it to a memory layer:

layer = QgsVectorLayer("Point?crs=EPSG:4326", "test", "memory")
layer.dataProvider().addAttributes([QgsField("dt", QVariant.DateTime)])
layer.updateFields()
QgsProject.instance().addMapLayer(layer, True)

s = "22/04/20 05:14:38:560000" # 560000 microsec = 560 millisec
# PyQt5 doesn't support microsec, so s[:-3]
dt = QDateTime.fromString(s[:-3], "yy/MM/dd HH:mm:ss:zzz").addYears(100)

feat = QgsFeature(layer.fields())
feat.setGeometry(QgsGeometry()) # empty geometry for test
feat["dt"] = dt

layer.dataProvider().addFeatures([feat])
layer.updateExtents()

But the millisecond part is missing in the attribute table.

enter image description here

How can I display the millisecond part in attribute table?

I do calculation at the level of milliseconds.

1
  • 2
    This might be of help. It appears you need to set the DateTime format for the field.
    – Matt
    Commented May 18, 2022 at 10:07

1 Answer 1

6

The comment by @Matt was already pointing in a correct direction. QgsDateTimeFieldFormatter is indeed needed to modify the display of DateTime values.

The following code example replaces the default DateTime formatter within the QgsFieldFormatterRegistry with a new formatter. The new formatter uses the given format string to parse any value.

class MyFormatter(QgsDateTimeFieldFormatter):
    
    config = {"display_format": "dd/MM/yyyy HH:mm:ss:zzz"} # your custom date time format
    
    def representValue(self, layer, fieldIndex, config, cache, value):
        return super().representValue(layer, fieldIndex, self.config, cache, value)
        

registry = QgsApplication.fieldFormatterRegistry()
registry.removeFieldFormatter('DateTime')
registry.addFieldFormatter(MyFormatter())

date_display

While writing this answer I just noticed that this approach removes the timezone string. I'm not sure at the moment on how to add it to the formatter.

Edit: As pointed out in the comments QgsDateTimeFieldFormatter formats all QDateTime, QDate and QTime values. In order to only modify the display of a single of those types implement a simple type check as below. QDate and QTime values should then stay the same.

def representValue(self, layer, fieldIndex, config, cache, value):
        if type(value) == QDateTime:
            return super().representValue(layer, fieldIndex, self.config, cache, value)
        
        return super().representValue(layer, fieldIndex, config, cache, value)
3
  • 1
    Thanks. Timezone is not necessary. It worked on DateTime format but it also changed only time (QTime) format to dd/MM/yyyy 10:20:32:000. It was displayed just 10:20:32 before this solution. I mean, this script adds dd/MM/yyy string and :000 to QTime value. -> i.sstatic.net/9lhr1.png Commented May 21, 2022 at 0:47
  • And it adds 00:00:00:000 to QDate fields. -> i.sstatic.net/ckjLH.png Commented May 21, 2022 at 0:56
  • @KadirŞahbaz Thanks for the notice. I didn't check other field types. I've updated my answer so that other values won't be modified. imgur.com/a/BR2gnnJ
    – CodeBard
    Commented May 21, 2022 at 13:31

Not the answer you're looking for? Browse other questions tagged or ask your own question.