[Interest] Question about setting QLocale
Thiago Macieira
thiago.macieira at intel.com
Mon Nov 30 20:29:52 CET 2015
On Monday 30 November 2015 18:58:53 Murphy, Sean wrote:
> Thanks for the quick reply, Thiago
>
> > That's a bug. And there's another bug in your reading/writing of the
> > string, but that's besides the point.
>
> Can you go into more details about this? I'd prefer to have no bugs! ;)
You said:
> it fails to convert because what's been written in the file for data recorded
> on a Friday is "ÖÜÎå"
That's Mojibake[1], which means you wrote to the file with one encoding and
read using another. The Chinese word for Friday is 周五, not "ÖÜÎå". Since
you're getting 4 characters instead of the Chinese two, I'm guessing the file
was written in GB18030 and read as Latin1[2]. A simple test confirms this:
$ echo 周五 | iconv -t gb18030 | iconv -f latin1
ÖÜÎå
[1] https://en.wikipedia.org/wiki/Mojibake
[2] if you had got six, I would have guessed writing as UTF-8 and reading as
Latin1; if you had got 4 replacement characters instead of letters in the
Latin-A Extended block, I would have guessed writing as GB18030 and reading as
UTF-8.
> > QString QDateTime::toString(const QString& format) const {
> >
> > return QLocale::system().toString(*this, format); }
> >
> > It should have been QLocale::c(). It's been like the above since 5.2.0 and
> > no one noticed. That is, btw, your workaround: use
> >
> > QLocale::c().toString(ample.sampleTime(), "ddd MM/dd/yyyy HH:mm:ss.zzz")
>
> Is that really a bug in Qt though?
Yes. QString, QByteArray, QDateTime, etc. should always use the C locale when
formatting their contents to a string and when parsing a string. That's so
that data files produced with those strings can be parsed when the locale
changes. That is to say, exactly your scenario.
Take, for example, one of the greatest design flaws of the C library: scanf and
printf. They always use the locale API to format the decimal and group
separators, which means they are wholly unsuitable for formatting data meant
to be portable. That's why QtCore carries its own code to format integers and
floating point to string, instead of using the C library.
That's why POSIX extends the C API with scanf_l and printf_l, fixing the design
flaw. Qt 5.7 will allow you to optionally use those (sscanf_l and snprintf_l)
if your C library has them.
> I'd think as a developer/user in a
> non-English speaking country that if I were to write out a date object
> using either the "ddd" or "dddd" options, that I would expect those to show
> up in my native language.
If you want locale-formatted output, use QLocale.
> This produces:
> DateTime: Saturday 01/01/2000 00:00:00.000
> Default: Samstag 01/01/2000 00:00:00.000
> C: Saturday 01/01/2000 00:00:00.000
> German: Samstag 01/01/2000 00:00:00.000
>
> So I'd think your proposal to change QDateTime::toString() to use
> QLocale::c() would be the wrong behavior.
It will be done. The question is whether we do it in 5.6, 5.7 or in 6.0. But
it will happen.
> If I'm in Germany, I'd expect to
> see Samstag, not Saturday.
Actually, your code is wrong. Let's use today's date instead:
DateTime: Monday 11/30/2015 00:00:00.000
Default: Montag 11/30/2015 00:00:00.000
C: Monday 11/30/2015 00:00:00.000
German: Montag 11/30/2015 00:00:00.000
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.
You may argue whether QDateTime::toString() should have done that by default.
My argument stands that QDateTime, like QString and QByteArray, should only
produce predictable output (not locale-dependent).
> Or am I making some other mistake in my test
> application (or misunderstanding what QLocale::c() actually does)? I'm
> assuming that the line: QLocale::setDefault(QLocale(QLocale::German,
> QLocale::Germany)); Fakes out the rest of the Qt classes to think I'm in
> Germany, although that first line I print out, where I use
> QDateTime::toString() and I'm getting it in English kind of says otherwise.
QLocale::setDefault() changes the default locale, not the system locale. The
system locale is determined by, well, the system. Consult its documentation on
how to change (you're on Windows, as proven by the Mojibake above).
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
More information about the Interest
mailing list