QDate in Qt5 now supports dates before 4712 BCE (new limit is 12626108195557530 BCE, well outside the limit of a four digit year). --- This fixes test #12: kdecore-kdatetimetest when building on Qt5. I choose to just rip it out rather than to preserve behaviour for Qt4, as I figgured we could live with a bad return value from outOfRange() until we drop Qt4 support from the frameworks branch.
kdecore/date/kdatetime.cpp | 233 +++++++++++++-------------------------- kdecore/date/kdatetime.h | 33 ++---- kdecore/tests/kdatetimetest.cpp | 4 - 3 filer ändrade, 86 tillägg(+), 184 borttagningar(-) diff --git a/kdecore/date/kdatetime.cpp b/kdecore/date/kdatetime.cpp index df1fc3d..9dd1b26 100644 --- a/kdecore/date/kdatetime.cpp +++ b/kdecore/date/kdatetime.cpp @@ -70,16 +70,8 @@ static const char longMonth[][10] = { "October", "November", "December" }; - -// The reason for the KDateTime being invalid, returned from KDateTime::fromString() -enum Status { - stValid = 0, // either valid, or really invalid - stTooEarly // invalid (valid date before QDate range) -}; - - static QDateTime fromStr(const QString& string, const QString& format, int& utcOffset, - QString& zoneName, QByteArray& zoneAbbrev, bool& dateOnly, Status&); + QString& zoneName, QByteArray& zoneAbbrev, bool& dateOnly); static int matchDay(const QString &string, int &offset, KCalendarSystem*); static int matchMonth(const QString &string, int &offset, KCalendarSystem*); static bool getUTCOffset(const QString &string, int &offset, bool colon, int &result); @@ -89,10 +81,8 @@ static int findString_internal(const QString &string, const char *ptr, int count template<int disp> static inline int findString(const QString &string, const char array[][disp], int count, int &offset) { return findString_internal(string, array[0], count, offset, disp); } -static QDate checkDate(int year, int month, int day, Status&); -static const int MIN_YEAR = -4712; // minimum year which QDate allows -static const int NO_NUMBER = 0x8000000; // indicates that no number is present in string conversion functions +static const int NO_NUMBER = std::numeric_limits<int>::min(); // indicates that no number is present in string conversion functions #ifdef COMPILING_TESTS KDECORE_EXPORT int KDateTime_utcCacheHit = 0; @@ -317,7 +307,6 @@ class KDateTimePrivate : public QSharedData KDateTimePrivate() : QSharedData(), specType(KDateTime::Invalid), - status(stValid), utcCached(true), convertedCached(false), m2ndOccurrence(false), @@ -329,7 +318,6 @@ class KDateTimePrivate : public QSharedData : QSharedData(), mDt(d), specType(s.type()), - status(stValid), utcCached(false), convertedCached(false), m2ndOccurrence(false), @@ -360,7 +348,6 @@ class KDateTimePrivate : public QSharedData ut(rhs.ut), converted(rhs.converted), specType(rhs.specType), - status(rhs.status), utcCached(rhs.utcCached), convertedCached(rhs.convertedCached), m2ndOccurrence(rhs.m2ndOccurrence), @@ -456,7 +443,6 @@ private: } converted; public: KDateTime::SpecType specType : 4; // time spec type (N.B. need 3 bits + sign bit, since enums are signed on some platforms) - Status status : 2; // reason for invalid status mutable bool utcCached : 1; // true if 'ut' is valid mutable bool convertedCached : 1; // true if 'converted' is valid mutable bool m2ndOccurrence : 1; // this is the second occurrence of a time zone time @@ -827,7 +813,6 @@ KDateTime &KDateTime::operator=(const KDateTime &other) void KDateTime::detach() { d.detach(); } bool KDateTime::isNull() const { return d->dt().isNull(); } bool KDateTime::isValid() const { return d->specType != Invalid && d->dt().isValid(); } -bool KDateTime::outOfRange() const { return d->status == stTooEarly; } bool KDateTime::isDateOnly() const { return d->dateOnly(); } bool KDateTime::isLocalZone() const { return d->specType == TimeZone && d->specZone == KSystemTimeZones::local(); } bool KDateTime::isClockTime() const { return d->specType == ClockTime; } @@ -1928,8 +1913,7 @@ KDateTime KDateTime::fromString(const QString &string, TimeFormat format, bool * } } } - Status invalid = stValid; - QDate qdate = checkDate(year, month+1, day, invalid); // convert date, and check for out-of-range + QDate qdate(year, month+1, day); // convert date, and check for out-of-range if (!qdate.isValid()) break; KDateTime result(qdate, QTime(hour, minute, second), Spec(OffsetFromUTC, offset)); @@ -1949,12 +1933,6 @@ KDateTime KDateTime::fromString(const QString &string, TimeFormat format, bool * if ((hour*3600 + minute*60 + 60 - offset + 86400*5) % 86400) // (max abs(offset) is 100 hours) break; // the time isn't the last second of the day } - if (invalid) - { - KDateTime dt; // date out of range - return invalid KDateTime ... - dt.d->status = invalid; // ... with reason for error - return dt; - } return result; } case RFC3339Date: // format is YYYY-MM-DDThh:mm:ss[.s]TZ @@ -2112,15 +2090,14 @@ KDateTime KDateTime::fromString(const QString &string, TimeFormat format, bool * } } int month, day; - Status invalid = stValid; if (parts[3].length() == 3) { // A day of the year is specified day = parts[3].toInt(&ok); if (!ok || day < 1 || day > 366) break; - d = checkDate(year, 1, 1, invalid).addDays(day - 1); // convert date, and check for out-of-range - if (!d.isValid() || (!invalid && d.year() != year)) + d = QDate(year, 1, 1).addDays(day - 1); // convert date, and check for out-of-range + if (!d.isValid() || (d.year() != year)) break; day = d.day(); month = d.month(); @@ -2132,18 +2109,12 @@ KDateTime KDateTime::fromString(const QString &string, TimeFormat format, bool * day = parts[3].right(2).toInt(&ok1); if (!ok || !ok1) break; - d = checkDate(year, month, day, invalid); // convert date, and check for out-of-range + d = QDate(year, month, day); // convert date, and check for out-of-range if (!d.isValid()) break; } if (dateOnly) { - if (invalid) - { - KDateTime dt; // date out of range - return invalid KDateTime ... - dt.d->status = invalid; // ... with reason for error - return dt; - } return KDateTime(d, Spec(ClockTime)); } if (hour == 24 && !minute && !second && !msecs) @@ -2159,12 +2130,6 @@ KDateTime KDateTime::fromString(const QString &string, TimeFormat format, bool * if (parts[8].isEmpty()) { // No UTC offset is specified. Don't try to validate leap seconds. - if (invalid) - { - KDateTime dt; // date out of range - return invalid KDateTime ... - dt.d->status = invalid; // ... with reason for error - return dt; - } return KDateTime(d, t, KDateTimePrivate::fromStringDefault()); } int offset = 0; @@ -2194,12 +2159,6 @@ KDateTime KDateTime::fromString(const QString &string, TimeFormat format, bool * if ((hour*3600 + minute*60 + 60 - offset + 86400*5) % 86400) // (max abs(offset) is 100 hours) break; // the time isn't the last second of the day } - if (invalid) - { - KDateTime dt; // date out of range - return invalid KDateTime ... - dt.d->status = invalid; // ... with reason for error - return dt; - } return KDateTime(d, t, Spec(spec, offset)); } case QtTextDate: // format is Wdy Mth DD [hh:mm:ss] YYYY [±hhmm] @@ -2274,10 +2233,9 @@ KDateTime KDateTime::fromString(const QString &string, const QString &format, { int utcOffset = 0; // UTC offset in seconds bool dateOnly = false; - Status invalid = stValid; QString zoneName; QByteArray zoneAbbrev; - QDateTime qdt = fromStr(string, format, utcOffset, zoneName, zoneAbbrev, dateOnly, invalid); + QDateTime qdt = fromStr(string, format, utcOffset, zoneName, zoneAbbrev, dateOnly); if (!qdt.isValid()) return KDateTime(); if (zones) @@ -2292,97 +2250,88 @@ KDateTime KDateTime::fromString(const QString &string, const QString &format, zone = zones->zone(zoneName); zname = true; } - else if (!invalid) + else if (!zoneAbbrev.isEmpty()) { - if (!zoneAbbrev.isEmpty()) + // A time zone abbreviation has been found. + // Use the time zone which contains it, if any, provided that the + // abbreviation applies at the specified date/time. + bool useUtcOffset = false; + const KTimeZones::ZoneMap z = zones->zones(); + for (KTimeZones::ZoneMap::ConstIterator it = z.constBegin(); it != z.constEnd(); ++it) { - // A time zone abbreviation has been found. - // Use the time zone which contains it, if any, provided that the - // abbreviation applies at the specified date/time. - bool useUtcOffset = false; - const KTimeZones::ZoneMap z = zones->zones(); - for (KTimeZones::ZoneMap::ConstIterator it = z.constBegin(); it != z.constEnd(); ++it) + if (it.value().abbreviations().contains(zoneAbbrev)) { - if (it.value().abbreviations().contains(zoneAbbrev)) + int offset2; + int offset = it.value().offsetAtZoneTime(qdt, &offset2); + QDateTime ut(qdt); + ut.setTimeSpec(Qt::UTC); + ut.addSecs(-offset); + if (it.value().abbreviation(ut) != zoneAbbrev) { - int offset2; - int offset = it.value().offsetAtZoneTime(qdt, &offset2); - QDateTime ut(qdt); - ut.setTimeSpec(Qt::UTC); - ut.addSecs(-offset); + if (offset == offset2) + continue; // abbreviation doesn't apply at specified time + ut.addSecs(offset - offset2); if (it.value().abbreviation(ut) != zoneAbbrev) - { - if (offset == offset2) - continue; // abbreviation doesn't apply at specified time - ut.addSecs(offset - offset2); - if (it.value().abbreviation(ut) != zoneAbbrev) - continue; // abbreviation doesn't apply at specified time - offset = offset2; - } - // Found a time zone which uses this abbreviation at the specified date/time - if (zone.isValid()) - { - // Abbreviation is used by more than one time zone - if (!offsetIfAmbiguous || offset != utcOffset) - return KDateTime(); - useUtcOffset = true; - } - else - { - zone = it.value(); - utcOffset = offset; - } + continue; // abbreviation doesn't apply at specified time + offset = offset2; + } + // Found a time zone which uses this abbreviation at the specified date/time + if (zone.isValid()) + { + // Abbreviation is used by more than one time zone + if (!offsetIfAmbiguous || offset != utcOffset) + return KDateTime(); + useUtcOffset = true; + } + else + { + zone = it.value(); + utcOffset = offset; } } - if (useUtcOffset) - { - zone = KTimeZone(); - if (!utcOffset) - qdt.setTimeSpec(Qt::UTC); - } - else - zname = true; } - else if (utcOffset || qdt.timeSpec() == Qt::UTC) + if (useUtcOffset) + { + zone = KTimeZone(); + if (!utcOffset) + qdt.setTimeSpec(Qt::UTC); + } + else + zname = true; + } + else if (utcOffset || qdt.timeSpec() == Qt::UTC) + { + // A UTC offset has been found. + // Use the time zone which contains it, if any. + // For a date-only value, use the start of the day. + QDateTime dtUTC = qdt; + dtUTC.setTimeSpec(Qt::UTC); + dtUTC.addSecs(-utcOffset); + const KTimeZones::ZoneMap z = zones->zones(); + for (KTimeZones::ZoneMap::ConstIterator it = z.constBegin(); it != z.constEnd(); ++it) { - // A UTC offset has been found. - // Use the time zone which contains it, if any. - // For a date-only value, use the start of the day. - QDateTime dtUTC = qdt; - dtUTC.setTimeSpec(Qt::UTC); - dtUTC.addSecs(-utcOffset); - const KTimeZones::ZoneMap z = zones->zones(); - for (KTimeZones::ZoneMap::ConstIterator it = z.constBegin(); it != z.constEnd(); ++it) + QList<int> offsets = it.value().utcOffsets(); + if ((offsets.isEmpty() || offsets.contains(utcOffset)) + && it.value().offsetAtUtc(dtUTC) == utcOffset) { - QList<int> offsets = it.value().utcOffsets(); - if ((offsets.isEmpty() || offsets.contains(utcOffset)) - && it.value().offsetAtUtc(dtUTC) == utcOffset) + // Found a time zone which uses this offset at the specified time + if (zone.isValid() || !utcOffset) { - // Found a time zone which uses this offset at the specified time - if (zone.isValid() || !utcOffset) - { - // UTC offset is used by more than one time zone - if (!offsetIfAmbiguous) - return KDateTime(); - if (invalid) - { - KDateTime dt; // date out of range - return invalid KDateTime ... - dt.d->status = invalid; // ... with reason for error - return dt; - } - if (dateOnly) - return KDateTime(qdt.date(), Spec(OffsetFromUTC, utcOffset)); - qdt.setTimeSpec(Qt::LocalTime); - return KDateTime(qdt, Spec(OffsetFromUTC, utcOffset)); - } - zone = it.value(); + // UTC offset is used by more than one time zone + if (!offsetIfAmbiguous) + return KDateTime(); + if (dateOnly) + return KDateTime(qdt.date(), Spec(OffsetFromUTC, utcOffset)); + qdt.setTimeSpec(Qt::LocalTime); + return KDateTime(qdt, Spec(OffsetFromUTC, utcOffset)); } + zone = it.value(); } } } if (!zone.isValid() && zname) return KDateTime(); // an unknown zone name or abbreviation was found - if (zone.isValid() && !invalid) + if (zone.isValid()) { if (dateOnly) return KDateTime(qdt.date(), Spec(zone)); @@ -2391,12 +2340,6 @@ KDateTime KDateTime::fromString(const QString &string, const QString &format, } // No time zone match was found - if (invalid) - { - KDateTime dt; // date out of range - return invalid KDateTime ... - dt.d->status = invalid; // ... with reason for error - return dt; - } KDateTime result; if (utcOffset) { @@ -2474,9 +2417,8 @@ QDataStream & operator>>(QDataStream &s, KDateTime &kdt) * utcOffset == 0, that indicates that no UTC offset was found. */ QDateTime fromStr(const QString& string, const QString& format, int& utcOffset, - QString& zoneName, QByteArray& zoneAbbrev, bool& dateOnly, Status &status) + QString& zoneName, QByteArray& zoneAbbrev, bool& dateOnly) { - status = stValid; QString str = string.simplified(); int year = NO_NUMBER; int month = NO_NUMBER; @@ -2796,10 +2738,10 @@ QDateTime fromStr(const QString& string, const QString& format, int& utcOffset, year = KDateTime::currentLocalDate().year(); if (month == NO_NUMBER) month = 1; - QDate d = checkDate(year, month, (day > 0 ? day : 1), status); // convert date, and check for out-of-range + QDate d = QDate(year, month, (day > 0 ? day : 1)); // convert date, and check for out-of-range if (!d.isValid()) return QDateTime(); - if (dayOfWeek != NO_NUMBER && !status) + if (dayOfWeek != NO_NUMBER) { if (day == NO_NUMBER) { @@ -3049,28 +2991,3 @@ int findString_internal(const QString &string, const char *array, int count, int } return -1; } - -/* - * Return the QDate for a given year, month and day. - * If in error, check whether the reason is that the year is out of range. - * If so, return a valid (but wrong) date but with 'status' set to the - * appropriate error code. If no error, 'status' is set to stValid. - */ -QDate checkDate(int year, int month, int day, Status &status) -{ - status = stValid; - QDate qdate(year, month, day); - if (qdate.isValid()) - return qdate; - - // Invalid date - check whether it's simply out of range - if (year < MIN_YEAR) - { - bool leap = (year % 4 == 0) && (year % 100 || year % 400 == 0); - qdate.setDate((leap ? 2000 : 2001), month, day); - if (qdate.isValid()) - status = stTooEarly; - } - return qdate; -} - diff --git a/kdecore/date/kdatetime.h b/kdecore/date/kdatetime.h index d0eb07d..03a757d 100644 --- a/kdecore/date/kdatetime.h +++ b/kdecore/date/kdatetime.h @@ -1291,19 +1291,13 @@ class KDECORE_EXPORT KDateTime //krazy:exclude=dpointer (implicitly shared) * to RFCDate. Only set it to RFCDateDay if you want to return an error * when the day of the week is omitted. * - * For @p format = ISODate or RFCDate[Day], if an invalid KDateTime is - * returned, you can check why @p format was considered invalid by use of - * outOfRange(). If that method returns true, it indicates that @p format - * was in fact valid, but the date lies outside the range which can be - * represented by QDate. - * * @param string string to convert * @param format format code. LocalDate cannot be used here. * @param negZero if non-null, the value is set to true if a UTC offset of * '-0000' is found or, for RFC 2822 format, an unrecognised * or invalid time zone abbreviation is found, else false. * @return KDateTime value, or an invalid KDateTime if either parameter is invalid - * @see setFromStringDefault(), toString(), outOfRange(), QString::fromString() + * @see setFromStringDefault(), toString(), QString::fromString() */ static KDateTime fromString(const QString &string, TimeFormat format = ISODate, bool *negZero = 0); @@ -1427,11 +1421,6 @@ class KDECORE_EXPORT KDateTime //krazy:exclude=dpointer (implicitly shared) * appears more than once but with different values, the weekday name does * not tally with the date, an invalid KDateTime is returned. * - * If an invalid KDateTime is returned, you can check why @p format was - * considered invalid by use of outOfRange(). If that method returns true, - * it indicates that @p format was in fact valid, but the date lies outside - * the range which can be represented by QDate. - * * @param string string to convert * @param format format string * @param zones time zone collection, or null for none @@ -1442,7 +1431,7 @@ class KDECORE_EXPORT KDateTime //krazy:exclude=dpointer (implicitly shared) * time zone information doesn't match any in @p zones, or if the * time zone information is ambiguous and @p offsetIfAmbiguous is * false - * @see setFromStringDefault(), toString(), outOfRange() + * @see setFromStringDefault(), toString() */ static KDateTime fromString(const QString &string, const QString &format, const KTimeZones *zones = 0, bool offsetIfAmbiguous = true); @@ -1463,17 +1452,17 @@ class KDECORE_EXPORT KDateTime //krazy:exclude=dpointer (implicitly shared) /** - * Checks whether the date/time returned by the last call to fromString() - * was invalid because an otherwise valid date was outside the range which - * can be represented by QDate. This status occurs when fromString() read - * a valid string containing a year earlier than -4712 (4713 BC). On exit - * from fromString(), if outOfRange() returns @c true, isValid() will - * return @c false. + * Always returns false, as dates earlier than -4712 are now supported by + * @c KDateTime. * - * @return @c true if date was earlier than -4712, else @c false - * @see isValid(), fromString() + * @return @c false + * @see isValid() + * @deprecated since 5.0, we now supports all valid dates. */ - bool outOfRange() const; + inline bool outOfRange() const + { + return false; + } /** * Compare this instance with another to determine whether they are diff --git a/kdecore/tests/kdatetimetest.cpp b/kdecore/tests/kdatetimetest.cpp index 812abc5..c38aea0 100644 --- a/kdecore/tests/kdatetimetest.cpp +++ b/kdecore/tests/kdatetimetest.cpp @@ -3803,10 +3803,6 @@ void KDateTimeTest::strings_format() s = dt.toString(QLatin1String("%Y")); QCOMPARE(s, QString::fromLatin1("123456")); - dt = KDateTime::fromString(QLatin1String("-471412311430:01.3+0500"), QLatin1String("%Y%m%d%H%M%:S%:s%z")); - QVERIFY(!dt.isValid()); // too early - QVERIFY(dt.outOfRange()); - dtutc = KDateTime::fromString(QLatin1String("2000-01-01T00:00:00.000+0000"), QLatin1String("%Y-%m-%dT%H:%M%:S%:s%z")); QVERIFY(dtutc.isValid()); dt = KDateTime::fromString(QLatin1String("2000-01-01T05:00:00.000+0500"), QLatin1String("%Y-%m-%dT%H:%M%:S%:s%z")); -- 1.7.10.4 _______________________________________________ Kde-frameworks-devel mailing list Kde-frameworks-devel@kde.org https://mail.kde.org/mailman/listinfo/kde-frameworks-devel