From 207954d5f0751c61f8d8b325797a806ef5f8c854 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 7 Jun 2023 14:08:15 +0200 Subject: Avoid using Darwin date formatting before 1583 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It turns out that Darwin's date formatting uses the Julian calendar for dates before 1582-10-15, when the Gregorian calendar first came into use (in some countries, while many others continued using Julian). This leads to discrepancies between the (Gregorian) dates we pass it for formatting and the (Julian) dates it actually prints, that are the same number of seconds before 1970. Previously the QLocale system backend for Darwin already had a kludge to work round its handling of negative years, so it suffices to extend that to years before 1583. Fixes: QTBUG-54955 Pick-to: 6.6 6.5 Change-Id: I70f219b73bf20c0cd63bcda2b0e99042354872ca Reviewed-by: MÃ¥rten Nordheim --- src/corelib/text/qlocale_mac.mm | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/corelib/text/qlocale_mac.mm b/src/corelib/text/qlocale_mac.mm index 12211975dd..4374a19e85 100644 --- a/src/corelib/text/qlocale_mac.mm +++ b/src/corelib/text/qlocale_mac.mm @@ -242,12 +242,6 @@ static QString macDateToStringImpl(QDate date, CFDateFormatterStyle style) // back to 1900. (Alaska and Phillipines may still be borked, though.) QCFType myDate = QDateTime(date, QTime(12, 0)).toCFDate(); QCFType mylocale = CFLocaleCopyCurrent(); - // Note: Darwin take the calendar transition from Julian to Gregorian into - // account (see QTBUG-54955, again). This means that, just before that - // transition, dates are off by ten days, drifting by one day per century - // before that, except when the century is a multiple of 400 years. Unless - // we can find a way to suppress that, we're stuck with bogus results for - // historic dates more than a few centuries back. QCFType myFormatter = CFDateFormatterCreate(kCFAllocatorDefault, mylocale, style, kCFDateFormatterNoStyle); @@ -259,12 +253,14 @@ static QVariant macDateToString(QDate date, bool short_format) { const int year = date.year(); QString fakeYear, trueYear; - if (year < 0) { + if (year < 1583) { // System API (in macOS 11.0, at least) discards sign :-( // Simply negating the year won't do as the resulting year typically has // a different pattern of week-days. + // Furthermore (see QTBUG-54955), Darwin uses the Julian calendar for + // dates before 1582-10-15, leading to discrepancies. int matcher = QGregorianCalendar::yearSharingWeekDays(date); - Q_ASSERT(matcher > 0); + Q_ASSERT(matcher >= 1583); Q_ASSERT(matcher % 100 != date.month()); Q_ASSERT(matcher % 100 != date.day()); // i.e. there can't be any confusion between the two-digit year and @@ -277,7 +273,7 @@ static QVariant macDateToString(QDate date, bool short_format) QString text = macDateToStringImpl(date, short_format ? kCFDateFormatterShortStyle : kCFDateFormatterLongStyle); - if (year < 0) { + if (year < 1583) { if (text.contains(fakeYear)) return std::move(text).replace(fakeYear, trueYear); // Cope with two-digit year: -- cgit v1.2.3