[PATCH] Remove KDateTime limitation of 4712 BCE [v2].

Jon Severinsson jon at severinsson.net
Mon Oct 8 14:44:17 UTC 2012


QDate in Qt5 now supports dates before 4712 BCE (new limit is 12626108195557530 BCE, well outside the limit of a four digit year).

V2 updates: Fixes the unit test to be usefull instead of removing it, updated documentation.
---

> Sure, remove the outOfRange check, but QVERIFY(dt.isValid()) or 
> QVERIFY(!dt.isValid()) could still be useful.

OK, did one better and made sure the date was a negative jd even when
interpreted as a Proleptic Gregorian date (as Qt5 does) rather than as
a Proleptic Julian date (as Qt4 does), and hid it in an Qt version
check (as when interpreted as a Proleptic Julian date it is well below
jd 0, and Qt4 uses an unsigned 32-bit integer for jd).

Also updated some more documentation to relflect the improved QDate
in Qt5 (eg is a Proleptic Gregorian with improved range).

 kdecore/date/kdatetime.cpp      |  233 +++++++++++++--------------------------
 kdecore/date/kdatetime.h        |   70 +++---------
 kdecore/tests/kdatetimetest.cpp |   11 +-
 3 filer ändrade, 94 tillägg(+), 220 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..fb496cd 100644
--- a/kdecore/date/kdatetime.h
+++ b/kdecore/date/kdatetime.h
@@ -52,12 +52,9 @@ class KDateTimeSpecPrivate;
  * can also be set to represent a date-only value with no associated time.
  *
  * The class uses QDateTime internally to represent date/time values, and
- * therefore uses the Gregorian calendar for dates starting from 15 October 1582,
- * and the Julian calendar for dates up to 4 October 1582. The minimum year
- * number is -4712 (4713 BC), while the upper limit is more than 11,000,000. The
- * actual adoption of the Gregorian calendar after 1582 was slow; the last European
- * country to adopt it, Greece, did so only in 1923. See QDateTime Considerations
- * section below for further discussion of the date range limitations.
+ * therefore uses the Gregorian calendar retroactively. If you need the Julian
+ * calendar for historical dates (as commonly used prior to some date between 1582
+ * and 1923 depending on nation), please use @c KCalendarSystem and related classes.
  *
  * The time specification types which KDateTime supports are:
  * - the UTC time zone
@@ -126,34 +123,6 @@ class KDateTimeSpecPrivate;
  * creation of a separate copy of the data (e.g. if you want two copies to
  * cache different time zone conversions), call detach().
  *
- * @section compatibility QDateTime Considerations
- *
- * KDateTime's interface is designed to be as compatible as possible with that
- * of QDateTime, but with adjustments to cater for time zone handling. Because
- * QDateTime lacks virtual methods, KDateTime is not inherited from QDateTime,
- * but instead is implemented using a private QDateTime object.
- *
- * The date range restriction due to the use of QDateTime internally may at
- * first sight seem a design limitation. However, two factors should be
- * considered:
- *
- * - there are significant problems in the representation of dates before the
- *   Gregorian calendar was adopted. The date of adoption of the Gregorian
- *   calendar varied from place to place, and in the Julian calendar the
- *   date of the new year varied so that in different places the year number
- *   could differ by one. So any date/time system which attempted to represent
- *   dates as actually used in history would be too specialized to belong to
- *   the core KDE libraries. Date/time systems for scientific applications can
- *   be much simpler, but may differ from historical records.
- *
- * - time zones were not invented until the middle of the 19th century. Before
- *   that, solar time was used.
- *
- * Because of these issues, together with the fact that KDateTime's aim is to
- * provide automatic time zone handling for date/time values, QDateTime was
- * chosen as the basis for KDateTime. For those who need an extended date
- * range, other classes exist.
- *
  * @section simulation Simulation Facility
  *
  * This class provides a facility to simulate the local system time, which
@@ -1291,19 +1260,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 +1390,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 +1400,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 +1421,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..7cc1269 100644
--- a/kdecore/tests/kdatetimetest.cpp
+++ b/kdecore/tests/kdatetimetest.cpp
@@ -3787,25 +3787,24 @@ void KDateTimeTest::strings_format()
     QCOMPARE(dt.dateTime(), QDateTime(QDate(-4712,9,5), QTime(14,30,1,300), Qt::LocalTime));
     QCOMPARE(dt.utcOffset(), 5*3600);
     QVERIFY(dt.isValid());
-    QVERIFY(!dt.outOfRange());
 
     dt = KDateTime::fromString(QLatin1String("999909051430:01.3+0500"), QLatin1String("%Y%m%d%H%M%:S%:s%z"));
     QCOMPARE(dt.dateTime(), QDateTime(QDate(9999,9,5), QTime(14,30,1,300), Qt::LocalTime));
     QCOMPARE(dt.utcOffset(), 5*3600);
     QVERIFY(dt.isValid());
-    QVERIFY(!dt.outOfRange());
 
     dt = KDateTime::fromString(QLatin1String("123456.09051430:01.3+0500"), QLatin1String("%:Y.%m%d%H%M%:S%:s%z"));
     QCOMPARE(dt.dateTime(), QDateTime(QDate(123456,9,5), QTime(14,30,1,300), Qt::LocalTime));
     QCOMPARE(dt.utcOffset(), 5*3600);
     QVERIFY(dt.isValid());
-    QVERIFY(!dt.outOfRange());
     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());
+#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
+    dt = KDateTime::fromString(QLatin1String("-471411231430:01.3+0500"), QLatin1String("%Y%m%d%H%M%:S%:s%z"));
+    QVERIFY(dt.isValid());
+    QVERIFY(dt.date().getJulianDay() == -1);
+#endif
 
     dtutc = KDateTime::fromString(QLatin1String("2000-01-01T00:00:00.000+0000"), QLatin1String("%Y-%m-%dT%H:%M%:S%:s%z"));
     QVERIFY(dtutc.isValid());
-- 
1.7.10.4



More information about the Kde-frameworks-devel mailing list