Skip to content
Permalink
Browse files
Merge pull request #45656 from Joonalai/fix-format-datetimes
Format date and datetime fields based on locale (#45617)
  • Loading branch information
elpaso committed Nov 12, 2021
2 parents f364690 + 8571e09 commit 5e671f481154276faf04d53b972cb7a06cf2424c
@@ -22,9 +22,9 @@ the field configuration.
#include "qgsdatetimefieldformatter.h"
%End
public:
static const QString DATE_FORMAT;
static QString DATE_FORMAT;
static const QString TIME_FORMAT;
static const QString DATETIME_FORMAT;
static QString DATETIME_FORMAT;
static const QString QT_ISO_FORMAT;
static const QString DISPLAY_FOR_ISO_FORMAT;

@@ -39,6 +39,11 @@ Default constructor of field formatter for a date time field.
virtual QString representValue( QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config, const QVariant &cache, const QVariant &value ) const;


static void applyLocaleChange();
%Docstring
Adjusts the date time formats according to locale.
%End

static QString defaultFormat( QVariant::Type type );
%Docstring
Gets the default format in function of the type.
@@ -113,6 +113,7 @@ typedef SInt32 SRefCon;

#include "qgsuserprofilemanager.h"
#include "qgsuserprofile.h"
#include "qgsdatetimefieldformatter.h"

#ifdef HAVE_OPENCL
#include "qgsopenclutils.h"
@@ -1029,6 +1030,9 @@ int main( int argc, char *argv[] )
}
QLocale::setDefault( currentLocale );

// Date time settings
QgsDateTimeFieldFormatter::applyLocaleChange();

QgsApplication::setTranslation( translationCode );
}

@@ -20,9 +20,9 @@
#include "qgsvectorlayer.h"
#include "qgsapplication.h"

const QString QgsDateTimeFieldFormatter::DATE_FORMAT = QStringLiteral( "yyyy-MM-dd" );
QString QgsDateTimeFieldFormatter::DATE_FORMAT = QStringLiteral( "yyyy-MM-dd" );
const QString QgsDateTimeFieldFormatter::TIME_FORMAT = QStringLiteral( "HH:mm:ss" );
const QString QgsDateTimeFieldFormatter::DATETIME_FORMAT = QStringLiteral( "yyyy-MM-dd HH:mm:ss" );
QString QgsDateTimeFieldFormatter::DATETIME_FORMAT = QStringLiteral( "yyyy-MM-dd HH:mm:ss" );
// we need to use Qt::ISODate rather than a string format definition in QDate::fromString
const QString QgsDateTimeFieldFormatter::QT_ISO_FORMAT = QStringLiteral( "Qt ISO Date" );
// but QDateTimeEdit::setDisplayFormat only accepts string formats, so use with time zone by default
@@ -62,6 +62,10 @@ QString QgsDateTimeFieldFormatter::representValue( QgsVectorLayer *layer, int fi
// we always show time zones for datetime values
showTimeZone = true;
}
else if ( static_cast<QMetaType::Type>( value.type() ) == QMetaType::QTime )
{
return value.toTime().toString( displayFormat );
}
else
{
if ( fieldIsoFormat )
@@ -94,6 +98,13 @@ QString QgsDateTimeFieldFormatter::representValue( QgsVectorLayer *layer, int fi
return result;
}

void QgsDateTimeFieldFormatter::applyLocaleChange()
{
QString dateFormat = QLocale().dateFormat( QLocale::FormatType::ShortFormat );
QgsDateTimeFieldFormatter::DATETIME_FORMAT = QString( "%1 %2" ).arg( dateFormat, QgsDateTimeFieldFormatter::TIME_FORMAT );
QgsDateTimeFieldFormatter::DATE_FORMAT = dateFormat;
}

QString QgsDateTimeFieldFormatter::defaultFormat( QVariant::Type type )
{
switch ( type )
@@ -31,9 +31,9 @@
class CORE_EXPORT QgsDateTimeFieldFormatter : public QgsFieldFormatter
{
public:
static const QString DATE_FORMAT;
static QString DATE_FORMAT;
static const QString TIME_FORMAT;
static const QString DATETIME_FORMAT;
static QString DATETIME_FORMAT;
static const QString QT_ISO_FORMAT;
static const QString DISPLAY_FOR_ISO_FORMAT;

@@ -46,6 +46,9 @@ class CORE_EXPORT QgsDateTimeFieldFormatter : public QgsFieldFormatter

QString representValue( QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config, const QVariant &cache, const QVariant &value ) const override;

//! Adjusts the date time formats according to locale.
static void applyLocaleChange();

/**
* Gets the default format in function of the type.
* The type is expected to be one of
@@ -682,31 +682,64 @@ def tearDownClass(cls):
QLocale.setDefault(QLocale(QLocale.English))

def test_representValue(self):
layer = QgsVectorLayer("point?field=int:integer&field=datetime:datetime&field=long:long",
layer = QgsVectorLayer("point?field=datetime:datetime&field=date:date&field=time:time",
"layer", "memory")
self.assertTrue(layer.isValid())
QgsProject.instance().addMapLayers([layer])

field_formatter = QgsDateTimeFieldFormatter()

# default configuration should show timezone information
config = {}
self.assertEqual(field_formatter.representValue(layer, 1, config, None,
QDateTime(QDate(2020, 3, 4), QTime(12, 13, 14), Qt.UTC)),
'2020-03-04 12:13:14 (UTC)')
self.assertEqual(field_formatter.representValue(layer, 1, config, None,
QDateTime(QDate(2020, 3, 4), QTime(12, 13, 14), Qt.OffsetFromUTC, 3600)),
'2020-03-04 12:13:14 (UTC+01:00)')

# if specific display format is set then use that
config = {"display_format": "dd/MM/yyyy HH:mm:ss"}
self.assertEqual(field_formatter.representValue(layer, 1, config, None,
self.assertEqual(field_formatter.representValue(layer, 0, config, None,
QDateTime(QDate(2020, 3, 4), QTime(12, 13, 14), Qt.UTC)),
'04/03/2020 12:13:14')
self.assertEqual(field_formatter.representValue(layer, 1, config, None,
self.assertEqual(field_formatter.representValue(layer, 0, config, None,
QDateTime(QDate(2020, 3, 4), QTime(12, 13, 14), Qt.OffsetFromUTC, 3600)),
'04/03/2020 12:13:14')

locale_assertions = {
QLocale(QLocale.English): {
"date_format": 'M/d/yy',
"time_format": 'HH:mm:ss',
"datetime_format": 'M/d/yy HH:mm:ss',
"datetime_utc": '3/4/20 12:13:14 (UTC)',
"datetime_utc+1": '3/4/20 12:13:14 (UTC+01:00)'
},
QLocale(QLocale.Finnish): {
"date_format": 'd.M.yyyy',
"time_format": 'HH:mm:ss',
"datetime_format": 'd.M.yyyy HH:mm:ss',
"datetime_utc": '4.3.2020 12:13:14 (UTC)',
"datetime_utc+1": '4.3.2020 12:13:14 (UTC+01:00)'
},
}

for locale, assertions in locale_assertions.items():
QLocale().setDefault(locale)
QgsDateTimeFieldFormatter.applyLocaleChange()
field_formatter = QgsDateTimeFieldFormatter()

self.assertEqual(field_formatter.defaultFormat(QVariant.Date), assertions["date_format"], locale.name())
self.assertEqual(field_formatter.defaultFormat(QVariant.Time), assertions["time_format"], locale.name())
self.assertEqual(field_formatter.defaultFormat(QVariant.DateTime), assertions["datetime_format"], locale.name())

# default configuration should show timezone information
config = {}
self.assertEqual(field_formatter.representValue(layer, 0, config, None,
QDateTime(QDate(2020, 3, 4), QTime(12, 13, 14), Qt.UTC)),
assertions["datetime_utc"], locale.name())
self.assertEqual(field_formatter.representValue(layer, 0, config, None,
QDateTime(QDate(2020, 3, 4), QTime(12, 13, 14), Qt.OffsetFromUTC, 3600)),
assertions["datetime_utc+1"], locale.name())
self.assertEqual(field_formatter.representValue(layer, 1, config, None,
QDate(2020, 3, 4)),
assertions["datetime_utc"].split(" ")[0], locale.name())
config = {"display_format": "HH:mm:s"}
self.assertEqual(field_formatter.representValue(layer, 2, config, None,
QTime(12, 13, 14)),
assertions["datetime_utc"].split(" ")[1], locale.name())


if __name__ == '__main__':
unittest.main()

0 comments on commit 5e671f4

Please sign in to comment.