[Interest] Question about setting QLocale

Thiago Macieira thiago.macieira at intel.com
Tue Dec 1 00:54:58 CET 2015


On Monday 30 November 2015 23:11:30 Murphy, Sean wrote:
> But now that I'm understanding this issue better, the documentation
> (http://doc.qt.io/qt-5/qdate.html#fromString) suggests that there is no bug
> at all, that what I'm seeing is the intended (or at least the documented)
> behavior, and I'm inclined to agree with that's the way it should be. It
> specifically states that using the expressions "ddd", "dddd", "MMM", and
> "MMMM" are going to use the system locale (QLocale::system()) to populate
> the output string, so that's my error using those expressions with
> QDateTime::toString() in my log file functions and not understanding the
> repercussions of that. The bug you want me to submit certainly immediately
> breaks the documentation. Not necessarily a deal breaker, documentation can
> be changed...

You're right that the code and the documentation are aligned. I'm saying that 
I want to change the behaviour, since we did the exact same change for QString 
and QByteArray for 5.0.

We may not be able to do it in 5.x, so it may have to way for 6.0.
 
> But in general there's two different issues really, there's displaying dates
> and times to users and outputting dates in a locale-agnostic way for text
> data files. If I submit this as a bug as you want me to, and it's fixed in
> the way you suggest, the DEFAULT behavior is going to be producing the
> English/US outputs for those expressions above, for all QDate/QDateTime
> objects, anywhere they're used, regardless of whether it's on the UI or in
> a text file. I still think I'd find it VERY odd as a non-English developer
> to have my application default to saying Monday, instead of Montag (or
> Lunes in Spanish, or whatever "Monday" translates to for my given locale).
> And if I'm just writing an application for me, my local friends/coworkers,
> etc., it isn't going to naturally occur to me that I need to go out of my
> way to specifically ask for dates to be in MY language. I'm an English
> speaking American and even I find that unnecessarily Amerocentric!

Again, it depends on what you're trying to do.

>From my point of view of QtCore maintainer, I want QDateTime, QString and 
QByteArray to be entirely locale-agnostic, just the same way I'd like QFile to 
provide filesystem access, not be a VFS layer -- that's why QAbstractFileEngine 
is not exported anymore in Qt 5. The locale database is a huge chunk of code 
and data, which in some constrained devices could be entirely missing. In this 
case, QLocale::system() queries the system API, which is also something that 
constrained devices could do without.

Another problem is that QLocale::system(), due to a design flaw, is not thread-
safe. That means Q{Date,Time,DateTime}::toString isn't thread-safe. I've been 
meaning to refactor this code for a while, but haven't found the time.

If you want to create locale code, you use QLocale, just the same way that 
translated strings use QTranslator and tr().
 
> I think a better fix would be that the to/from string functions in
> QDate/QDateTime like
> QDate QDate::fromString(const QString & string, const
> QString & format) Be modified to
>   QDate QDate::fromString(const QString & string, const QString & format,
> const QLocale& locale = QLocale::system())

Not going to add that if its implementation would be:

	return locale.fromString(string, format);

Qt has convenience API, but not when it's dead simple like this.

And, again, this would imply that the only way to parse dates would require 
QLocale, with its problems. That's not proper layering of the classes.
 
> And add a note in the documentation that states that when using these types
> of functions in data files where there's a reasonable chance locales will
> be crossed, that it is recommended that the developer passes in
> QLocale::c() as the third parameter to ensure compatibility. I think the
> use case for wanting those date & time strings to be localized on their UI
> HAS to be more common than log files being passed between countries. 

Understood, but I disagree.
 
> > If I am in Germany, I'd expect to see 30.11.2015 (dd.MM.yyyy), not
> > MM/dd/yyyy like you used. So your code should have used QLocale to format
> > the date, asking it for the proper date-time formatting string.

> Now when you say I "should have used QLocale to format the date, asking it
> for the proper date-time formatting string", are you talking about this
> function, where QLocale takes over all the formatting
> QDateTime
> QLocale::toDateTime(const QString & string, FormatType format = LongFormat)
> const 
> Not the one I used?

Yes and no. Using the overload with FormatType is the best way for showing 
strings to the user, since there may be details that you wouldn't know 
otherwise. You should also use the QDateTime::toString overload taking an enum 
even for machine exchange, as it has Qt::RFC2822Date and Qt::ISODate (RFC 
3337).

But you can ask QLocale for the pattern itself, using dateFormat, timeFormat 
or dateTimeFormat(). If needed, you could modify the pattern, but I advise 
against it. That's about the only use-case I'd advise using raw patterns: 
getting it from QLocale to display to the user, let the user edit it if they 
want to, then format. But you need to be careful if QLocale::system() changes, 
so you don't use an old pattern from a language with the month and day names 
from another language!

> I think the downside to using QLocale's built-in formats is that I as the
> developer lose a LOT of control over what fields get written out and in
> what order. Maybe I wanted time first, then date. Maybe I want the

That's why you don't use them for data exchange. Use RFC2822Date or ISODate.

> localized abbreviated day of week and the abbreviated month name. Maybe I
> want the localized version "Monday" but I don't want the time zone
> information. QLocale::toString(const QDate & date, FormatType format) has
> very limited flexibility. And the string format version provides no way to
> produce "11/30/2015" or "30.11.2015" from a QDate based on locale. Right?

Sure it does.
 
> So I'd think that sticking with the string format is better, but we'd need
> some more expressions. Something like 'g' to mean "print the delimited date
> correctly for the desired locale", so the date January 12, 2016 using 'g'
> (minimum digits for days, 2 digit year) would be expressed as 1/12/16 in
> the US and 12.1.16 in Germany. Then "gg" (two digits for days, 2 digits for
> year) could be 01/12/16 (12.01.16), "ggg" (minimum digits for days, 4 digit
> year) would be 1/12/2016 (12.1.2016) and "gggg" (2 digit days, 4 digit
> year) is 01/12/2016 (12.01.2016). 

I disagree on two levels. First, that we need those at all, since we have the 
overloads taking enums. Second, even if we had them, there's no need to 
distinguish between leading zeroes or not: if you're going to delegate to the 
locale format, you don't get to choose.

Anyway, you're missing QLocale::NarrowFormat.
 
> Right now I don't see a way for me to say "Mon, 11/30/2015 5:12 PM"
> (abbreviated day name, properly delimited full date) in a platform agnostic
> way using either the QLocale path or the QDate/QDateTime path. The existing
> QDate/QDateTime classes begin to go a long ways down the path of letting
> the developer dictate exactly how dates should appear, I just think they
> don't go far enough when considering locales. 

Because I don't see why you'd want that format. Either you want to display 
something following the rules for the locale or you don't.
 
> I still think just switching the QDate/QDateTime to/from String functions to
> default to use QLocale::c() creates more problems than it solves, though.
 
Which is probably why we won't do it in 5.x. But it should happen in 6.0.

-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Software Architect - Intel Open Source Technology Center




More information about the Interest mailing list