> 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:

I learned a new word today! 

> > 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.

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...

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!

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())

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. 

> > 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.

Fair point, although honestly with my example I was really only trying to 
understand the behavior of the "dddd" expression with regard to locales, so I 
should have really just been using "dddd" as my format string instead of 
bringing in all the MM, dd, yyyy, HH, mm, ss, zzz stuff. 

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?
  QDateTime QLocale::toDateTime(const QString & string, const QString & format) 
const

If that's what you meant, that certainly doesn't solve everything either. The 
choices for format are QLocale::LongFormat and QLocale::ShortFormat (and 
NarrowFormat too, but that isn't substantially different than ShortFormat). 
These produce these outputs in my little test application respectively:
  QLocale::LongFormat
  C: Monday, 30 November 2015 16:17:17 Eastern Standard Time
  System: Monday, November 30, 2015 4:17:17 PM
  German: Montag, 30. November 2015 16:17:17 Eastern Standard Time

  QLocale::ShortFormat
  C: 30 Nov 2015 16:17:17
  System: 11/30/2015 4:17 PM
  German: 30.11.15 16:17

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 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?

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). 

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. 

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.

Sean

_______________________________________________
Interest mailing list
[email protected]
http://lists.qt-project.org/mailman/listinfo/interest

Reply via email to