diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp index 7790e9669a8..51b19b1957c 100644 --- a/src/corelib/time/qdatetime.cpp +++ b/src/corelib/time/qdatetime.cpp @@ -1731,14 +1731,10 @@ QDate QDate::fromString(QStringView string, Qt::DateFormat format) default for \a baseYear, selecting a year from then to 1999. Passing 1976 as \a baseYear will select a year from 1976 through 2075, for example. When the format also includes month, day (of month) and day-of-week, these suffice to - imply the century. Parsing all but the day of week and then using - QCalendar::matchCenturyToWeekday() to combine that with the day of the week - could disambiguate such a date, but runs the risk of turning a user error - - that would otherwise be recognized by the invalid result of parsing - into a - valid result in another century, that wasn't the user's intent. At present, - the date parser only considers the century indicated by \a baseYear and the - centuries immediately after and before it, to limit the scope for such - mistakes. See \l {Date ambiguities} for further details, + imply the century. In such a case, a matching date is selected in the + nearest century to the one indicated by \a baseYear, prefering later over + earlier. See \l QCalendar::matchCenturyToWeekday() and \l {Date ambiguities} + for further details, The following examples demonstrate the default values: @@ -1774,15 +1770,12 @@ QDate QDate::fromString(QStringView string, Qt::DateFormat format) Including a day of the week in the format can also resolve the century of a date specified using only the last two digits of its year. Unfortunately, when combined with a date in which the user (or other source of data) has - mixed up two of the fields, this resolution could lead to finding a date - which does match the format's reading but isn't the one intended by its - author. This would be in a different century, which would in many cases at - least make it possible to recognize there is a problem with the data. At - present, date parsing considers the centuries after and before the one - indicated by \a baseYear, which may fall foul of this problem. See the - discussion above about using QCalendar::matchCenturyToWeekday() to extend - that to a wider range of centuries, if that can safely be applied in your - use-case. + mixed up two of the fields, this resolution can lead to finding a date which + does match the format's reading but isn't the one intended by its author. + Likewise, if the user simply gets the day of the week wrong, in an otherwise + correct date, this can lead a date in a different century. In each case, + finding a date in a different century can turn a wrongly-input date into a + wildly different one. The best way to avoid date ambiguities is to use four-digit years and months specified by name (whether full or abbreviated), ideally collected via user diff --git a/src/corelib/time/qdatetimeparser.cpp b/src/corelib/time/qdatetimeparser.cpp index 6837caaa8a1..f50b3b0d3f3 100644 --- a/src/corelib/time/qdatetimeparser.cpp +++ b/src/corelib/time/qdatetimeparser.cpp @@ -1120,20 +1120,11 @@ static QDate actualDate(QDateTimeParser::Sections known, const QCalendar &calend if ((known & QDateTimeParser::YearSection) == 0) { if (known & QDateTimeParser::YearSection2Digits) { - /* - Two-digit year and month are specified; choice of century can only - fix this if diff is in one of {1, 2, 5} or {2, 4, 6}; but not if - diff is in the other. It's also only reasonable to consider - adjacent century, e.g. if year thinks it's 2012 and two-digit year - is '97, it makes sense to consider 1997. If either adjacent - century does work, the other won't. - */ - actual = QDate(year + 100, month, day, calendar); - if (calendar.dayOfWeek(actual) == dayofweek) - return actual; - actual = QDate(year - 100, month, day, calendar); - if (calendar.dayOfWeek(actual) == dayofweek) + actual = calendar.matchCenturyToWeekday({year, month, day}, dayofweek); + if (actual.isValid()) { + Q_ASSERT(calendar.dayOfWeek(actual) == dayofweek); return actual; + } } else { // Offset by 7 is usually enough, but rare cases may need more: for (int y = 1; y < 12; y++) {