QDateTime - Switch to using the QLocale date formatter

Switch the implementation of toString() methods in QDate, QTime and
QDateTime to use the QLocale formatter, and remove the now redundant
QDateTime formatter.

Change-Id: Ie4f17c8a6e31acde3ce066f19835bb2b83351ce8
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Mitch Curtis <mitch.curtis@digia.com>
bb10
John Layt 2013-07-26 22:08:15 +01:00 committed by The Qt Project
parent dd488bb7a4
commit 35af88b37e
2 changed files with 16 additions and 254 deletions

View File

@ -168,8 +168,8 @@ int qt_monthNumberFromShortName(const QString &shortName)
return -1;
}
#endif
#ifndef QT_NO_DATESTRING
static QString fmtDateTime(const QString& f, const QTime* dt = 0, const QDate* dd = 0);
static void rfcDateImpl(const QString &s, QDate *dd = 0, QTime *dt = 0, int *utfcOffset = 0);
#endif
static QDateTimePrivate::Spec utcToLocal(QDate &date, QTime &time);
@ -964,14 +964,14 @@ QString QDate::toString(Qt::DateFormat f) const
range 0 to 9999. This restriction may apply to locale-aware
formats as well, depending on the locale settings.
\sa QDateTime::toString(), QTime::toString()
\sa QDateTime::toString(), QTime::toString(), QLocale::toString()
*/
QString QDate::toString(const QString& format) const
{
if (year() > 9999)
return QString();
return fmtDateTime(format, 0, this);
return QLocale::system().toString(*this, format);
}
#endif //QT_NO_DATESTRING
@ -1720,11 +1720,11 @@ QString QTime::toString(Qt::DateFormat format) const
If the time is invalid, an empty string will be returned.
If \a format is empty, the default format "hh:mm:ss" is used.
\sa QDate::toString(), QDateTime::toString()
\sa QDate::toString(), QDateTime::toString(), QLocale::toString()
*/
QString QTime::toString(const QString& format) const
{
return fmtDateTime(format, this, 0);
return QLocale::system().toString(*this, format);
}
#endif //QT_NO_DATESTRING
/*!
@ -2977,11 +2977,11 @@ QString QDateTime::toString(Qt::DateFormat f) const
If the datetime is invalid, an empty string will be returned.
\sa QDate::toString(), QTime::toString()
\sa QDate::toString(), QTime::toString(), QLocale::toString()
*/
QString QDateTime::toString(const QString& format) const
{
return fmtDateTime(format, &d->time, &d->date);
return QLocale::system().toString(*this, format);
}
#endif //QT_NO_DATESTRING
@ -4162,200 +4162,11 @@ QDataStream &operator>>(QDataStream &in, QDateTime &dateTime)
#endif // QT_NO_DATASTREAM
// checks if there is an unquoted 'AP' or 'ap' in the string
static bool hasUnquotedAP(const QString &f)
{
const QLatin1Char quote('\'');
bool inquote = false;
const int max = f.size();
for (int i=0; i<max; ++i) {
if (f.at(i) == quote) {
inquote = !inquote;
} else if (!inquote && f.at(i).toUpper() == QLatin1Char('A')) {
return true;
}
}
return false;
}
#ifndef QT_NO_DATESTRING
/*****************************************************************************
Some static function used by QDate, QTime and QDateTime
*****************************************************************************/
// Replaces tokens by their value. See QDateTime::toString() for a list of valid tokens
static QString getFmtString(const QString& f, const QTime* dt = 0, const QDate* dd = 0, bool am_pm = false)
{
if (f.isEmpty())
return QString();
QString buf = f;
int removed = 0;
if (dt) {
if (f.startsWith(QLatin1String("hh")) || f.startsWith(QLatin1String("HH"))) {
const bool hour12 = f.at(0) == QLatin1Char('h') && am_pm;
if (hour12 && dt->hour() > 12)
buf = QString::number(dt->hour() - 12).rightJustified(2, QLatin1Char('0'), true);
else if (hour12 && dt->hour() == 0)
buf = QLatin1String("12");
else
buf = QString::number(dt->hour()).rightJustified(2, QLatin1Char('0'), true);
removed = 2;
} else if (f.at(0) == QLatin1Char('h') || f.at(0) == QLatin1Char('H')) {
const bool hour12 = f.at(0) == QLatin1Char('h') && am_pm;
if (hour12 && dt->hour() > 12)
buf = QString::number(dt->hour() - 12);
else if (hour12 && dt->hour() == 0)
buf = QLatin1String("12");
else
buf = QString::number(dt->hour());
removed = 1;
} else if (f.startsWith(QLatin1String("mm"))) {
buf = QString::number(dt->minute()).rightJustified(2, QLatin1Char('0'), true);
removed = 2;
} else if (f.at(0) == (QLatin1Char('m'))) {
buf = QString::number(dt->minute());
removed = 1;
} else if (f.startsWith(QLatin1String("ss"))) {
buf = QString::number(dt->second()).rightJustified(2, QLatin1Char('0'), true);
removed = 2;
} else if (f.at(0) == QLatin1Char('s')) {
buf = QString::number(dt->second());
} else if (f.startsWith(QLatin1String("zzz"))) {
buf = QString::number(dt->msec()).rightJustified(3, QLatin1Char('0'), true);
removed = 3;
} else if (f.at(0) == QLatin1Char('z')) {
buf = QString::number(dt->msec());
removed = 1;
} else if (f.at(0).toUpper() == QLatin1Char('A')) {
const bool upper = f.at(0) == QLatin1Char('A');
buf = dt->hour() < 12 ? QLatin1String("am") : QLatin1String("pm");
if (upper)
buf = buf.toUpper();
if (f.size() > 1 && f.at(1).toUpper() == QLatin1Char('P') &&
f.at(0).isUpper() == f.at(1).isUpper()) {
removed = 2;
} else {
removed = 1;
}
}
}
if (dd) {
if (f.startsWith(QLatin1String("dddd"))) {
buf = dd->longDayName(dd->dayOfWeek());
removed = 4;
} else if (f.startsWith(QLatin1String("ddd"))) {
buf = dd->shortDayName(dd->dayOfWeek());
removed = 3;
} else if (f.startsWith(QLatin1String("dd"))) {
buf = QString::number(dd->day()).rightJustified(2, QLatin1Char('0'), true);
removed = 2;
} else if (f.at(0) == QLatin1Char('d')) {
buf = QString::number(dd->day());
removed = 1;
} else if (f.startsWith(QLatin1String("MMMM"))) {
buf = dd->longMonthName(dd->month());
removed = 4;
} else if (f.startsWith(QLatin1String("MMM"))) {
buf = dd->shortMonthName(dd->month());
removed = 3;
} else if (f.startsWith(QLatin1String("MM"))) {
buf = QString::number(dd->month()).rightJustified(2, QLatin1Char('0'), true);
removed = 2;
} else if (f.at(0) == QLatin1Char('M')) {
buf = QString::number(dd->month());
removed = 1;
} else if (f.startsWith(QLatin1String("yyyy"))) {
const int year = dd->year();
buf = QString::number(qAbs(year)).rightJustified(4, QLatin1Char('0'));
if(year > 0)
removed = 4;
else
{
buf.prepend(QLatin1Char('-'));
removed = 5;
}
} else if (f.startsWith(QLatin1String("yy"))) {
buf = QString::number(dd->year()).right(2).rightJustified(2, QLatin1Char('0'));
removed = 2;
}
}
if (removed == 0 || removed >= f.size()) {
return buf;
}
return buf + getFmtString(f.mid(removed), dt, dd, am_pm);
}
// Parses the format string and uses getFmtString to get the values for the tokens. Ret
static QString fmtDateTime(const QString& f, const QTime* dt, const QDate* dd)
{
QString buf;
if (f.isEmpty())
return buf;
if (dt && !dt->isValid())
return buf;
if (dd && !dd->isValid())
return buf;
const bool ap = hasUnquotedAP(f);
QString frm;
uint status = '0';
for (int i = 0, n = f.length(); i < n; ++i) {
const QChar c = f.at(i);
const uint cc = c.unicode();
if (cc == '\'') {
if (status == cc) {
if (i > 0 && f.at(i - 1).unicode() == cc)
buf += c;
status = '0';
} else {
if (!frm.isEmpty()) {
buf += getFmtString(frm, dt, dd, ap);
frm.clear();
}
status = cc;
}
} else if (status == '\'') {
buf += c;
} else if (c == status) {
if (ap && (cc == 'P' || cc == 'p'))
status = '0';
frm += c;
} else {
buf += getFmtString(frm, dt, dd, ap);
frm.clear();
if (cc == 'h' || cc == 'm' || cc == 'H' || cc == 's' || cc == 'z') {
status = cc;
frm += c;
} else if (cc == 'd' || cc == 'M' || cc == 'y') {
status = cc;
frm += c;
} else if (ap && cc == 'A') {
status = 'P';
frm += c;
} else if (ap && cc == 'a') {
status = 'p';
frm += c;
} else {
buf += c;
status = '0';
}
}
}
buf += getFmtString(frm, dt, dd, ap);
return buf;
}
#ifndef QT_NO_DATESTRING
static void rfcDateImpl(const QString &s, QDate *dd, QTime *dt, int *utcOffset)
{
int day = -1;
@ -4419,6 +4230,7 @@ static void rfcDateImpl(const QString &s, QDate *dd, QTime *dt, int *utcOffset)
}
#endif // QT_NO_DATESTRING
#ifdef Q_OS_WIN
static const int LowerYear = 1980;
#else

View File

@ -88,7 +88,6 @@ private slots:
void toString_rfcDate_data();
void toString_rfcDate();
void toString_enumformat();
void toString_strformat_data();
void toString_strformat();
void addDays();
void addMonths();
@ -1700,64 +1699,15 @@ void tst_QDateTime::operator_insert_extract()
}
#endif
void tst_QDateTime::toString_strformat_data()
{
QTest::addColumn<QDateTime>("dt");
QTest::addColumn<QString>("format");
QTest::addColumn<QString>("str");
QTest::newRow( "datetime0" ) << QDateTime() << QString("dd-MM-yyyy hh:mm:ss") << QString();
QTest::newRow( "datetime1" ) << QDateTime(QDate(1999, 12, 31), QTime(23, 59, 59, 999))
<< QString("dd-'mmddyy'MM-yyyy hh:mm:ss.zzz")
<< QString("31-mmddyy12-1999 23:59:59.999");
QTest::newRow( "datetime2" ) << QDateTime(QDate(1999, 12, 31), QTime(23, 59, 59, 999))
<< QString("dd-'apAP'MM-yyyy hh:mm:ss.zzz")
<< QString("31-apAP12-1999 23:59:59.999");
QTest::newRow( "datetime3" ) << QDateTime(QDate(1999, 12, 31), QTime(23, 59, 59, 999))
<< QString("Apdd-MM-yyyy hh:mm:ss.zzz")
<< QString("PMp31-12-1999 11:59:59.999");
QTest::newRow( "datetime4" ) << QDateTime(QDate(1999, 12, 31), QTime(23, 59, 59, 999))
<< QString("'ap'apdd-MM-yyyy 'AP'hh:mm:ss.zzz")
<< QString("appm31-12-1999 AP11:59:59.999");
QTest::newRow( "datetime5" ) << QDateTime(QDate(1999, 12, 31), QTime(23, 59, 59, 999))
<< QString("'''") << QString("'");
QTest::newRow( "datetime6" ) << QDateTime(QDate(1999, 12, 31), QTime(23, 59, 59, 999))
<< QString("'ap") << QString("ap");
QTest::newRow( "datetime7" ) << QDateTime(QDate(1999, 12, 31), QTime(23, 59, 59, 999))
<< QString("' ' 'hh' hh") << QString(" hh 23");
QTest::newRow( "datetime8" ) << QDateTime(QDate(1999, 12, 31), QTime(23, 59, 59, 999))
<< QString("d'foobar'") << QString("31foobar");
QTest::newRow( "datetime9" ) << QDateTime(QDate(1999, 12, 31), QTime(3, 59, 59, 999))
<< QString("hhhhh") << QString("03033");
QTest::newRow( "datetime11" ) << QDateTime(QDate(1999, 12, 31), QTime(23, 59, 59, 999))
<< QString("HHHhhhAaAPap") << QString("23231111PMpmPMpm");
QTest::newRow( "datetime12" ) << QDateTime(QDate(1999, 12, 31), QTime(3, 59, 59, 999))
<< QString("HHHhhhAaAPap") << QString("033033AMamAMam");
QTest::newRow( "datetime13" ) << 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( "single, 0 => 12 AM" ) << QDateTime(QDate(1999, 12, 31), QTime(0, 59, 59, 999))
<< QString("hAP") << QString("12AM");
QTest::newRow( "double, 0 => 12 AM" ) << QDateTime(QDate(1999, 12, 31), QTime(0, 59, 59, 999))
<< QString("hhAP") << QString("12AM");
QTest::newRow( "dddd" ) << QDateTime(QDate(1999, 12, 31), QTime(0, 59, 59, 999))
<< QString("dddd") << QString("Friday");
QTest::newRow( "ddd" ) << QDateTime(QDate(1999, 12, 31), QTime(0, 59, 59, 999))
<< QString("ddd") << QString("Fri");
QTest::newRow( "MMMM" ) << QDateTime(QDate(1999, 12, 31), QTime(0, 59, 59, 999))
<< QString("MMMM") << QString("December");
QTest::newRow( "MMM" ) << QDateTime(QDate(1999, 12, 31), QTime(0, 59, 59, 999))
<< QString("MMM") << QString("Dec");
QTest::newRow( "emtpy" ) << QDateTime(QDate(1999, 12, 31), QTime(0, 59, 59, 999))
<< QString("") << QString("");
}
void tst_QDateTime::toString_strformat()
{
QFETCH( QDateTime, dt );
QFETCH( QString, format );
QFETCH( QString, str );
QCOMPARE( dt.toString( format ), str );
// Most tests are in QLocale, just test that the api works.
QDate testDate(2013, 1, 1);
QTime testTime(1, 2, 3);
QDateTime testDateTime(testDate, testTime, Qt::UTC);
QCOMPARE(testDate.toString("yyyy-MM-dd"), QString("2013-01-01"));
QCOMPARE(testTime.toString("hh:mm:ss"), QString("01:02:03"));
QCOMPARE(testDateTime.toString("yyyy-MM-dd hh:mm:ss t"), QString("2013-01-01 01:02:03 UTC"));
}
void tst_QDateTime::fromStringDateFormat_data()