diff options
-rw-r--r-- | src/corelib/tools/qlocale.cpp | 137 | ||||
-rw-r--r-- | src/corelib/tools/qlocale_p.h | 3 | ||||
-rw-r--r-- | tests/auto/corelib/tools/qlocale/tst_qlocale.cpp | 100 |
3 files changed, 163 insertions, 77 deletions
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index e8e4c9ad67..060b220a4a 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -1574,7 +1574,7 @@ QString QLocale::toString(qulonglong i) const QString QLocale::toString(const QDate &date, const QString &format) const { - return d->dateTimeToString(format, &date, 0, this); + return d->dateTimeToString(format, QDateTime(), date, QTime(), this); } /*! @@ -1618,33 +1618,6 @@ static bool timeFormatContainsAP(const QString &format) return false; } -static QString timeZone() -{ -#if defined(Q_OS_WINCE) - TIME_ZONE_INFORMATION info; - DWORD res = GetTimeZoneInformation(&info); - if (res == TIME_ZONE_ID_UNKNOWN) - return QString(); - return QString::fromWCharArray(info.StandardName); -#elif defined(Q_OS_WIN) - _tzset(); -# if defined(_MSC_VER) && _MSC_VER >= 1400 - size_t returnSize = 0; - char timeZoneName[512]; - if (_get_tzname(&returnSize, timeZoneName, 512, 1)) - return QString(); - return QString::fromLocal8Bit(timeZoneName); -# else - return QString::fromLocal8Bit(_tzname[1]); -# endif -#elif defined(Q_OS_VXWORKS) - return QString(); -#else - tzset(); - return QString::fromLocal8Bit(tzname[1]); -#endif -} - /*! Returns a localized string representation of the given \a time according to the specified \a format. @@ -1652,7 +1625,7 @@ static QString timeZone() */ QString QLocale::toString(const QTime &time, const QString &format) const { - return d->dateTimeToString(format, 0, &time, this); + return d->dateTimeToString(format, QDateTime(), QDate(), time, this); } /*! @@ -1665,9 +1638,7 @@ QString QLocale::toString(const QTime &time, const QString &format) const QString QLocale::toString(const QDateTime &dateTime, const QString &format) const { - const QDate dt = dateTime.date(); - const QTime tm = dateTime.time(); - return d->dateTimeToString(format, &dt, &tm, this); + return d->dateTimeToString(format, dateTime, QDate(), QTime(), this); } /*! @@ -2553,28 +2524,27 @@ QString QLocale::pmText() const } -QString QLocalePrivate::dateTimeToString(const QString &format, const QDate *date, const QTime *time, +QString QLocalePrivate::dateTimeToString(const QString &format, const QDateTime &datetime, + const QDate &dateOnly, const QTime &timeOnly, const QLocale *q) const { - Q_ASSERT(date || time); - if ((date && !date->isValid()) || (time && !time->isValid())) + QDate date; + QTime time; + bool formatDate = false; + bool formatTime = false; + if (datetime.isValid()) { + date = datetime.date(); + time = datetime.time(); + formatDate = true; + formatTime = true; + } else if (dateOnly.isValid()) { + date = dateOnly; + formatDate = true; + } else if (timeOnly.isValid()) { + time = timeOnly; + formatTime = true; + } else { return QString(); - const bool format_am_pm = time && timeFormatContainsAP(format); - - enum { AM, PM } am_pm = AM; - int hour12 = time ? time->hour() : -1; - if (time) { - if (hour12 == 0) { - am_pm = AM; - hour12 = 12; - } else if (hour12 < 12) { - am_pm = AM; - } else if (hour12 == 12) { - am_pm = PM; - } else { - am_pm = PM; - hour12 -= 12; - } } QString result; @@ -2589,7 +2559,7 @@ QString QLocalePrivate::dateTimeToString(const QString &format, const QDate *dat const QChar c = format.at(i); int repeat = qt_repeatCount(format, i); bool used = false; - if (date) { + if (formatDate) { switch (c.unicode()) { case 'y': used = true; @@ -2599,11 +2569,14 @@ QString QLocalePrivate::dateTimeToString(const QString &format, const QDate *dat repeat = 2; switch (repeat) { - case 4: - result.append(longLongToString(date->year(), -1, 10, 4, QLocalePrivate::ZeroPadded)); + case 4: { + const int yr = date.year(); + const int len = (yr < 0) ? 5 : 4; + result.append(longLongToString(yr, -1, 10, len, QLocalePrivate::ZeroPadded)); break; + } case 2: - result.append(longLongToString(date->year() % 100, -1, 10, 2, + result.append(longLongToString(date.year() % 100, -1, 10, 2, QLocalePrivate::ZeroPadded)); break; default: @@ -2618,16 +2591,16 @@ QString QLocalePrivate::dateTimeToString(const QString &format, const QDate *dat repeat = qMin(repeat, 4); switch (repeat) { case 1: - result.append(longLongToString(date->month())); + result.append(longLongToString(date.month())); break; case 2: - result.append(longLongToString(date->month(), -1, 10, 2, QLocalePrivate::ZeroPadded)); + result.append(longLongToString(date.month(), -1, 10, 2, QLocalePrivate::ZeroPadded)); break; case 3: - result.append(q->monthName(date->month(), QLocale::ShortFormat)); + result.append(q->monthName(date.month(), QLocale::ShortFormat)); break; case 4: - result.append(q->monthName(date->month(), QLocale::LongFormat)); + result.append(q->monthName(date.month(), QLocale::LongFormat)); break; } break; @@ -2637,16 +2610,16 @@ QString QLocalePrivate::dateTimeToString(const QString &format, const QDate *dat repeat = qMin(repeat, 4); switch (repeat) { case 1: - result.append(longLongToString(date->day())); + result.append(longLongToString(date.day())); break; case 2: - result.append(longLongToString(date->day(), -1, 10, 2, QLocalePrivate::ZeroPadded)); + result.append(longLongToString(date.day(), -1, 10, 2, QLocalePrivate::ZeroPadded)); break; case 3: - result.append(q->dayName(date->dayOfWeek(), QLocale::ShortFormat)); + result.append(q->dayName(date.dayOfWeek(), QLocale::ShortFormat)); break; case 4: - result.append(q->dayName(date->dayOfWeek(), QLocale::LongFormat)); + result.append(q->dayName(date.dayOfWeek(), QLocale::LongFormat)); break; } break; @@ -2655,12 +2628,18 @@ QString QLocalePrivate::dateTimeToString(const QString &format, const QDate *dat break; } } - if (!used && time) { + if (!used && formatTime) { switch (c.unicode()) { case 'h': { used = true; repeat = qMin(repeat, 2); - const int hour = format_am_pm ? hour12 : time->hour(); + int hour = time.hour(); + if (timeFormatContainsAP(format)) { + if (hour > 12) + hour -= 12; + else if (hour == 0) + hour = 12; + } switch (repeat) { case 1: @@ -2677,10 +2656,10 @@ QString QLocalePrivate::dateTimeToString(const QString &format, const QDate *dat repeat = qMin(repeat, 2); switch (repeat) { case 1: - result.append(longLongToString(time->hour())); + result.append(longLongToString(time.hour())); break; case 2: - result.append(longLongToString(time->hour(), -1, 10, 2, QLocalePrivate::ZeroPadded)); + result.append(longLongToString(time.hour(), -1, 10, 2, QLocalePrivate::ZeroPadded)); break; } break; @@ -2690,10 +2669,10 @@ QString QLocalePrivate::dateTimeToString(const QString &format, const QDate *dat repeat = qMin(repeat, 2); switch (repeat) { case 1: - result.append(longLongToString(time->minute())); + result.append(longLongToString(time.minute())); break; case 2: - result.append(longLongToString(time->minute(), -1, 10, 2, QLocalePrivate::ZeroPadded)); + result.append(longLongToString(time.minute(), -1, 10, 2, QLocalePrivate::ZeroPadded)); break; } break; @@ -2703,10 +2682,10 @@ QString QLocalePrivate::dateTimeToString(const QString &format, const QDate *dat repeat = qMin(repeat, 2); switch (repeat) { case 1: - result.append(longLongToString(time->second())); + result.append(longLongToString(time.second())); break; case 2: - result.append(longLongToString(time->second(), -1, 10, 2, QLocalePrivate::ZeroPadded)); + result.append(longLongToString(time.second(), -1, 10, 2, QLocalePrivate::ZeroPadded)); break; } break; @@ -2718,7 +2697,7 @@ QString QLocalePrivate::dateTimeToString(const QString &format, const QDate *dat } else { repeat = 1; } - result.append(am_pm == AM ? q->amText().toLower() : q->pmText().toLower()); + result.append(time.hour() < 12 ? q->amText().toLower() : q->pmText().toLower()); break; case 'A': @@ -2728,7 +2707,7 @@ QString QLocalePrivate::dateTimeToString(const QString &format, const QDate *dat } else { repeat = 1; } - result.append(am_pm == AM ? q->amText().toUpper() : q->pmText().toUpper()); + result.append(time.hour() < 12 ? q->amText().toUpper() : q->pmText().toUpper()); break; case 'z': @@ -2740,10 +2719,10 @@ QString QLocalePrivate::dateTimeToString(const QString &format, const QDate *dat } switch (repeat) { case 1: - result.append(longLongToString(time->msec())); + result.append(longLongToString(time.msec())); break; case 3: - result.append(longLongToString(time->msec(), -1, 10, 3, QLocalePrivate::ZeroPadded)); + result.append(longLongToString(time.msec(), -1, 10, 3, QLocalePrivate::ZeroPadded)); break; } break; @@ -2751,8 +2730,14 @@ QString QLocalePrivate::dateTimeToString(const QString &format, const QDate *dat case 't': used = true; repeat = 1; - result.append(timeZone()); + // If we have a QDateTime use the time spec otherwise use the current system tzname + if (formatDate) { + result.append(datetime.timeZoneAbbreviation()); + } else { + result.append(QDateTime::currentDateTime().timeZoneAbbreviation()); + } break; + default: break; } diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h index 34223d5af9..4b4606ffab 100644 --- a/src/corelib/tools/qlocale_p.h +++ b/src/corelib/tools/qlocale_p.h @@ -330,7 +330,8 @@ public: enum NumberMode { IntegerMode, DoubleStandardMode, DoubleScientificMode }; bool validateChars(const QString &str, NumberMode numMode, QByteArray *buff, int decDigits = -1) const; - QString dateTimeToString(const QString &format, const QDate *date, const QTime *time, + QString dateTimeToString(const QString &format, const QDateTime &datetime, + const QDate &dateOnly, const QTime &timeOnly, const QLocale *q) const; const QLocaleData *m_data; diff --git a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp index 0c4dde4b1a..ea0e90a503 100644 --- a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp +++ b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp @@ -163,6 +163,7 @@ private slots: void formatTime_data(); void formatDateTime(); void formatDateTime_data(); + void formatTimeZone(); void toDateTime_data(); void toDateTime(); void negativeNumbers(); @@ -199,6 +200,7 @@ private slots: private: QString m_decimal, m_thousand, m_sdate, m_ldate, m_time; QString m_sysapp; + bool europeanTimeZone; #ifdef Q_OS_BLACKBERRY int m_languageFd; @@ -208,6 +210,11 @@ private: tst_QLocale::tst_QLocale() { qRegisterMetaType<QLocale::FormatType>("QLocale::FormatType"); + + // Test if in Central European Time zone + uint x1 = QDateTime(QDate(1990, 1, 1), QTime()).toTime_t(); + uint x2 = QDateTime(QDate(1990, 6, 1), QTime()).toTime_t(); + europeanTimeZone = (x1 == 631148400 && x2 == 644191200); } void tst_QLocale::initTestCase() @@ -1198,6 +1205,59 @@ void tst_QLocale::formatDateTime_data() QTest::newRow("28no_NO") << "no_NO" << QDateTime() << "'\"yymm\"'" << ""; + QDateTime testLongHour(QDate(1999, 12, 31), QTime(23, 59, 59, 999)); + QDateTime testShortHour(QDate(1999, 12, 31), QTime(3, 59, 59, 999)); + QDateTime testZeroHour(QDate(1999, 12, 31), QTime(0, 59, 59, 999)); + + QTest::newRow("datetime0") << "en_US" << QDateTime() + << QString("dd-MM-yyyy hh:mm:ss") << QString(); + QTest::newRow("datetime1") << "en_US" << testLongHour + << QString("dd-'mmddyy'MM-yyyy hh:mm:ss.zzz") + << QString("31-mmddyy12-1999 23:59:59.999"); + QTest::newRow("datetime2") << "en_US" << testLongHour + << QString("dd-'apAP'MM-yyyy hh:mm:ss.zzz") + << QString("31-apAP12-1999 23:59:59.999"); + QTest::newRow("datetime3") << "en_US" << testLongHour + << QString("Apdd-MM-yyyy hh:mm:ss.zzz") + << QString("PMp31-12-1999 11:59:59.999"); + QTest::newRow("datetime4") << "en_US" << testLongHour + << QString("'ap'apdd-MM-yyyy 'AP'hh:mm:ss.zzz") + << QString("appm31-12-1999 AP11:59:59.999"); + QTest::newRow("datetime5") << "en_US" << testLongHour + << QString("'''") << QString("'"); + QTest::newRow("datetime6") << "en_US" << testLongHour + << QString("'ap") << QString("ap"); + QTest::newRow("datetime7") << "en_US" << testLongHour + << QString("' ' 'hh' hh") << QString(" hh 23"); + QTest::newRow("datetime8") << "en_US" << testLongHour + << QString("d'foobar'") << QString("31foobar"); + QTest::newRow("datetime9") << "en_US" << testShortHour + << QString("hhhhh") << QString("03033"); + QTest::newRow("datetime11") << "en_US" << testLongHour + << QString("HHHhhhAaAPap") << QString("23231111PMpmPMpm"); + QTest::newRow("datetime12") << "en_US" << testShortHour + << QString("HHHhhhAaAPap") << QString("033033AMamAMam"); + QTest::newRow("datetime13") << "en_US" << QDateTime(QDate(1974, 12, 1), QTime(14, 14, 20)) + << QString("hh''mm''ss dd''MM''yyyy") + << QString("14'14'20 01'12'1974"); + QTest::newRow("AM no p") << "en_US" << testZeroHour + << QString("hhAX") << QString("12AMX"); + QTest::newRow("AM no p, x 2") << "en_US" << testShortHour + << QString("hhhhhaA") << QString("03033amAM"); + QTest::newRow("am 0 hour") << "en_US" << testZeroHour + << QString("hAP") << QString("12AM"); + QTest::newRow("AM zero hour") << "en_US" << testZeroHour + << QString("hhAP") << QString("12AM"); + QTest::newRow("dddd") << "en_US" << testZeroHour + << QString("dddd") << QString("Friday"); + QTest::newRow("ddd") << "en_US" << testZeroHour + << QString("ddd") << QString("Fri"); + QTest::newRow("MMMM") << "en_US" << testZeroHour + << QString("MMMM") << QString("December"); + QTest::newRow("MMM") << "en_US" << testZeroHour + << QString("MMM") << QString("Dec"); + QTest::newRow("empty") << "en_US" << testZeroHour + << QString("") << QString(""); } void tst_QLocale::formatDateTime() @@ -1211,6 +1271,46 @@ void tst_QLocale::formatDateTime() QCOMPARE(l.toString(dateTime, format), result); } +void tst_QLocale::formatTimeZone() +{ + QLocale enUS("en_US"); + + QDateTime dt1(QDate(2013, 1, 1), QTime(1, 0, 0), Qt::OffsetFromUTC, 60 * 60); + QCOMPARE(enUS.toString(dt1, "t"), QString("UTC+01:00")); + + QDateTime dt2(QDate(2013, 1, 1), QTime(1, 0, 0), Qt::OffsetFromUTC, -60 * 60); + QCOMPARE(enUS.toString(dt2, "t"), QString("UTC-01:00")); + + QDateTime dt3(QDate(2013, 1, 1), QTime(0, 0, 0), Qt::UTC); + QCOMPARE(enUS.toString(dt3, "t"), QString("UTC")); + + // LocalTime should vary + if (europeanTimeZone) { + // Time definitely in Standard Time + QDateTime dt4(QDate(2013, 1, 1), QTime(0, 0, 0), Qt::LocalTime); +#ifdef Q_OS_WIN + QEXPECT_FAIL("", "Windows only returns long name (QTBUG-32759)", Continue); +#endif // Q_OS_WIN + QCOMPARE(enUS.toString(dt4, "t"), QString("CET")); + + // Time definitely in Daylight Time + QDateTime dt5(QDate(2013, 6, 1), QTime(0, 0, 0), Qt::LocalTime); +#ifdef Q_OS_WIN + QEXPECT_FAIL("", "Windows only returns long name (QTBUG-32759)", Continue); +#endif // Q_OS_WIN + QCOMPARE(enUS.toString(dt5, "t"), QString("CEST")); + } else { + QSKIP("You must test using Central European (CET/CEST) time zone, e.g. TZ=Europe/Oslo"); + } + + // Current datetime should return current abbreviation + QCOMPARE(enUS.toString(QDateTime::currentDateTime(), "t"), + QDateTime::currentDateTime().timeZoneAbbreviation()); + + // Time on its own will always be current local time zone + QCOMPARE(enUS.toString(QTime(1, 2, 3), "t"), QDateTime::currentDateTime().timeZoneAbbreviation()); +} + void tst_QLocale::toDateTime_data() { QTest::addColumn<QString>("localeName"); |