1/****************************************************************************
2**
3** Copyright (C) 2020 The Qt Company Ltd.
4** Copyright (C) 2016 Intel Corporation.
5** Contact: https://www.qt.io/licensing/
6**
7** This file is part of the test suite of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:GPL-EXCEPT$
10** Commercial License Usage
11** Licensees holding valid commercial Qt licenses may use this file in
12** accordance with the commercial license agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and The Qt Company. For licensing terms
15** and conditions see https://www.qt.io/terms-conditions. For further
16** information use the contact form at https://www.qt.io/contact-us.
17**
18** GNU General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU
20** General Public License version 3 as published by the Free Software
21** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
22** included in the packaging of this file. Please review the following
23** information to ensure the GNU General Public License requirements will
24** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25**
26** $QT_END_LICENSE$
27**
28****************************************************************************/
29
30#include <private/qglobal_p.h> // for the icu feature test
31#include <QtTest/QtTest>
32#include <qdatetime.h>
33#include <qlocale.h>
34
35class tst_QDate : public QObject
36{
37 Q_OBJECT
38private slots:
39 void isNull_data();
40 void isNull();
41 void isValid_data();
42 void isValid();
43 void julianDay_data();
44 void julianDay();
45 void dayOfWeek_data();
46 void dayOfWeek();
47 void dayOfYear_data();
48 void dayOfYear();
49 void daysInMonth_data();
50 void daysInMonth();
51 void daysInYear_data();
52 void daysInYear();
53 void getDate();
54 void weekNumber_invalid_data();
55 void weekNumber_invalid();
56 void weekNumber_data();
57 void weekNumber();
58#if QT_CONFIG(timezone)
59 void startOfDay_endOfDay_data();
60 void startOfDay_endOfDay();
61#endif
62 void startOfDay_endOfDay_fixed_data();
63 void startOfDay_endOfDay_fixed();
64 void startOfDay_endOfDay_bounds();
65 void julianDaysLimits();
66 void addDays_data();
67 void addDays();
68 void addMonths_data();
69 void addMonths();
70 void addYears_data();
71 void addYears();
72 void daysTo();
73 void operator_eq_eq_data();
74 void operator_eq_eq();
75 void operator_lt();
76 void operator_gt();
77 void operator_lt_eq();
78 void operator_gt_eq();
79 void operator_insert_extract_data();
80 void operator_insert_extract();
81 void fromStringDateFormat_data();
82 void fromStringDateFormat();
83 void fromStringFormat_data();
84 void fromStringFormat();
85 void toStringFormat_data();
86 void toStringFormat();
87 void toStringDateFormat_data();
88 void toStringDateFormat();
89 void isLeapYear();
90 void yearsZeroToNinetyNine();
91 void printNegativeYear_data() const;
92 void printNegativeYear() const;
93#if QT_CONFIG(textdate) && QT_DEPRECATED_SINCE(5, 10)
94 void shortDayName() const;
95 void standaloneShortDayName() const;
96 void longDayName() const;
97 void standaloneLongDayName() const;
98 void shortMonthName() const;
99 void standaloneShortMonthName() const;
100 void longMonthName() const;
101 void standaloneLongMonthName() const;
102 void roundtripString() const;
103#endif // textdate
104 void roundtrip() const;
105 void qdebug() const;
106private:
107 QDate defDate() const { return QDate(1900, 1, 1); }
108 QDate invalidDate() const { return QDate(); }
109};
110
111Q_DECLARE_METATYPE(Qt::DateFormat)
112
113void tst_QDate::isNull_data()
114{
115 QTest::addColumn<qint64>(name: "jd");
116 QTest::addColumn<bool>(name: "null");
117
118 qint64 minJd = Q_INT64_C(-784350574879);
119 qint64 maxJd = Q_INT64_C( 784354017364);
120
121 QTest::newRow(dataTag: "qint64 min") << std::numeric_limits<qint64>::min() << true;
122 QTest::newRow(dataTag: "minJd - 1") << minJd - 1 << true;
123 QTest::newRow(dataTag: "minJd") << minJd << false;
124 QTest::newRow(dataTag: "minJd + 1") << minJd + 1 << false;
125 QTest::newRow(dataTag: "maxJd - 1") << maxJd - 1 << false;
126 QTest::newRow(dataTag: "maxJd") << maxJd << false;
127 QTest::newRow(dataTag: "maxJd + 1") << maxJd + 1 << true;
128 QTest::newRow(dataTag: "qint64 max") << std::numeric_limits<qint64>::max() << true;
129}
130
131void tst_QDate::isNull()
132{
133 QFETCH(qint64, jd);
134
135 QDate d = QDate::fromJulianDay(jd_: jd);
136 QTEST(d.isNull(), "null");
137}
138
139void tst_QDate::isValid_data()
140{
141 qint64 nullJd = std::numeric_limits<qint64>::min();
142
143 QTest::addColumn<int>(name: "year");
144 QTest::addColumn<int>(name: "month");
145 QTest::addColumn<int>(name: "day");
146 QTest::addColumn<qint64>(name: "jd");
147 QTest::addColumn<bool>(name: "valid");
148
149 QTest::newRow(dataTag: "0-0-0") << 0 << 0 << 0 << nullJd << false;
150 QTest::newRow(dataTag: "month 0") << 2000 << 0 << 1 << nullJd << false;
151 QTest::newRow(dataTag: "day 0") << 2000 << 1 << 0 << nullJd << false;
152
153 QTest::newRow(dataTag: "month 13") << 2000 << 13 << 1 << nullJd << false;
154
155 // test leap years
156 QTest::newRow(dataTag: "non-leap") << 2006 << 2 << 29 << nullJd << false;
157 QTest::newRow(dataTag: "normal leap") << 2004 << 2 << 29 << qint64(2453065) << true;
158 QTest::newRow(dataTag: "century leap 1900") << 1900 << 2 << 29 << nullJd << false;
159 QTest::newRow(dataTag: "century leap 2100") << 2100 << 2 << 29 << nullJd << false;
160 QTest::newRow(dataTag: "400-years leap 2000") << 2000 << 2 << 29 << qint64(2451604) << true;
161 QTest::newRow(dataTag: "400-years leap 2400") << 2400 << 2 << 29 << qint64(2597701) << true;
162 QTest::newRow(dataTag: "400-years leap 1600") << 1600 << 2 << 29 << qint64(2305507) << true;
163 QTest::newRow(dataTag: "year 0") << 0 << 2 << 27 << nullJd << false;
164
165 // Test end of four-digit years:
166 QTest::newRow(dataTag: "late") << 9999 << 12 << 31 << qint64(5373484) << true;
167
168 // test the number of days in months:
169 QTest::newRow(dataTag: "jan") << 2000 << 1 << 31 << qint64(2451575) << true;
170 QTest::newRow(dataTag: "feb") << 2000 << 2 << 29 << qint64(2451604) << true; // same data as 400-years leap
171 QTest::newRow(dataTag: "mar") << 2000 << 3 << 31 << qint64(2451635) << true;
172 QTest::newRow(dataTag: "apr") << 2000 << 4 << 30 << qint64(2451665) << true;
173 QTest::newRow(dataTag: "may") << 2000 << 5 << 31 << qint64(2451696) << true;
174 QTest::newRow(dataTag: "jun") << 2000 << 6 << 30 << qint64(2451726) << true;
175 QTest::newRow(dataTag: "jul") << 2000 << 7 << 31 << qint64(2451757) << true;
176 QTest::newRow(dataTag: "aug") << 2000 << 8 << 31 << qint64(2451788) << true;
177 QTest::newRow(dataTag: "sep") << 2000 << 9 << 30 << qint64(2451818) << true;
178 QTest::newRow(dataTag: "oct") << 2000 << 10 << 31 << qint64(2451849) << true;
179 QTest::newRow(dataTag: "nov") << 2000 << 11 << 30 << qint64(2451879) << true;
180 QTest::newRow(dataTag: "dec") << 2000 << 12 << 31 << qint64(2451910) << true;
181
182 // and invalid dates:
183 QTest::newRow(dataTag: "ijan") << 2000 << 1 << 32 << nullJd << false;
184 QTest::newRow(dataTag: "ifeb") << 2000 << 2 << 30 << nullJd << false;
185 QTest::newRow(dataTag: "imar") << 2000 << 3 << 32 << nullJd << false;
186 QTest::newRow(dataTag: "iapr") << 2000 << 4 << 31 << nullJd << false;
187 QTest::newRow(dataTag: "imay") << 2000 << 5 << 32 << nullJd << false;
188 QTest::newRow(dataTag: "ijun") << 2000 << 6 << 31 << nullJd << false;
189 QTest::newRow(dataTag: "ijul") << 2000 << 7 << 32 << nullJd << false;
190 QTest::newRow(dataTag: "iaug") << 2000 << 8 << 32 << nullJd << false;
191 QTest::newRow(dataTag: "isep") << 2000 << 9 << 31 << nullJd << false;
192 QTest::newRow(dataTag: "ioct") << 2000 << 10 << 32 << nullJd << false;
193 QTest::newRow(dataTag: "inov") << 2000 << 11 << 31 << nullJd << false;
194 QTest::newRow(dataTag: "idec") << 2000 << 12 << 32 << nullJd << false;
195
196 // the beginning of the Julian Day calendar:
197 QTest::newRow(dataTag: "jd earliest formula") << -4800 << 1 << 1 << qint64( -31738) << true;
198 QTest::newRow(dataTag: "jd -1") << -4714 << 11 << 23 << qint64( -1) << true;
199 QTest::newRow(dataTag: "jd 0") << -4714 << 11 << 24 << qint64( 0) << true;
200 QTest::newRow(dataTag: "jd 1") << -4714 << 11 << 25 << qint64( 1) << true;
201 QTest::newRow(dataTag: "jd latest formula") << 1400000 << 12 << 31 << qint64(513060925) << true;
202}
203
204void tst_QDate::isValid()
205{
206 QFETCH(int, year);
207 QFETCH(int, month);
208 QFETCH(int, day);
209 QFETCH(qint64, jd);
210 QFETCH(bool, valid);
211
212 QCOMPARE(QDate::isValid(year, month, day), valid);
213
214 QDate d;
215 d.setDate(year, month, day);
216 QCOMPARE(d.isValid(), valid);
217 QCOMPARE(d.toJulianDay(), jd);
218
219 if (valid) {
220 QCOMPARE(d.year(), year);
221 QCOMPARE(d.month(), month);
222 QCOMPARE(d.day(), day);
223 } else {
224 QCOMPARE(d.year(), 0);
225 QCOMPARE(d.month(), 0);
226 QCOMPARE(d.day(), 0);
227 }
228}
229
230void tst_QDate::julianDay_data()
231{
232 isValid_data();
233}
234
235void tst_QDate::julianDay()
236{
237 QFETCH(int, year);
238 QFETCH(int, month);
239 QFETCH(int, day);
240 QFETCH(qint64, jd);
241
242 {
243 QDate d;
244 d.setDate(year, month, day);
245 QCOMPARE(d.toJulianDay(), jd);
246 }
247
248 if (jd != std::numeric_limits<qint64>::min()) {
249 QDate d = QDate::fromJulianDay(jd_: jd);
250 QCOMPARE(d.year(), year);
251 QCOMPARE(d.month(), month);
252 QCOMPARE(d.day(), day);
253 }
254}
255
256void tst_QDate::dayOfWeek_data()
257{
258 QTest::addColumn<int>(name: "year");
259 QTest::addColumn<int>(name: "month");
260 QTest::addColumn<int>(name: "day");
261 QTest::addColumn<int>(name: "dayOfWeek");
262
263 QTest::newRow(dataTag: "data0") << 0 << 0 << 0 << 0;
264 QTest::newRow(dataTag: "data1") << 2000 << 1 << 3 << 1;
265 QTest::newRow(dataTag: "data2") << 2000 << 1 << 4 << 2;
266 QTest::newRow(dataTag: "data3") << 2000 << 1 << 5 << 3;
267 QTest::newRow(dataTag: "data4") << 2000 << 1 << 6 << 4;
268 QTest::newRow(dataTag: "data5") << 2000 << 1 << 7 << 5;
269 QTest::newRow(dataTag: "data6") << 2000 << 1 << 8 << 6;
270 QTest::newRow(dataTag: "data7") << 2000 << 1 << 9 << 7;
271 QTest::newRow(dataTag: "data8") << -4800 << 1 << 1 << 1;
272 QTest::newRow(dataTag: "data9") << -4800 << 1 << 2 << 2;
273 QTest::newRow(dataTag: "data10") << -4800 << 1 << 3 << 3;
274 QTest::newRow(dataTag: "data11") << -4800 << 1 << 4 << 4;
275 QTest::newRow(dataTag: "data12") << -4800 << 1 << 5 << 5;
276 QTest::newRow(dataTag: "data13") << -4800 << 1 << 6 << 6;
277 QTest::newRow(dataTag: "data14") << -4800 << 1 << 7 << 7;
278 QTest::newRow(dataTag: "data15") << -4800 << 1 << 8 << 1;
279}
280
281void tst_QDate::dayOfWeek()
282{
283 QFETCH(int, year);
284 QFETCH(int, month);
285 QFETCH(int, day);
286 QFETCH(int, dayOfWeek);
287
288 QDate dt(year, month, day);
289 QCOMPARE(dt.dayOfWeek(), dayOfWeek);
290}
291
292void tst_QDate::dayOfYear_data()
293{
294 QTest::addColumn<int>(name: "year");
295 QTest::addColumn<int>(name: "month");
296 QTest::addColumn<int>(name: "day");
297 QTest::addColumn<int>(name: "dayOfYear");
298
299 QTest::newRow(dataTag: "data0") << 0 << 0 << 0 << 0;
300 QTest::newRow(dataTag: "data1") << 2000 << 1 << 1 << 1;
301 QTest::newRow(dataTag: "data2") << 2000 << 1 << 2 << 2;
302 QTest::newRow(dataTag: "data3") << 2000 << 1 << 3 << 3;
303 QTest::newRow(dataTag: "data4") << 2000 << 12 << 31 << 366;
304 QTest::newRow(dataTag: "data5") << 2001 << 12 << 31 << 365;
305 QTest::newRow(dataTag: "data6") << 1815 << 1 << 1 << 1;
306 QTest::newRow(dataTag: "data7") << 1815 << 12 << 31 << 365;
307 QTest::newRow(dataTag: "data8") << 1500 << 1 << 1 << 1;
308 QTest::newRow(dataTag: "data9") << 1500 << 12 << 31 << 365;
309 QTest::newRow(dataTag: "data10") << -1500 << 1 << 1 << 1;
310 QTest::newRow(dataTag: "data11") << -1500 << 12 << 31 << 365;
311 QTest::newRow(dataTag: "data12") << -4800 << 1 << 1 << 1;
312 QTest::newRow(dataTag: "data13") << -4800 << 12 << 31 << 365;
313}
314
315void tst_QDate::dayOfYear()
316{
317 QFETCH(int, year);
318 QFETCH(int, month);
319 QFETCH(int, day);
320 QFETCH(int, dayOfYear);
321
322 QDate dt(year, month, day);
323 QCOMPARE(dt.dayOfYear(), dayOfYear);
324}
325
326void tst_QDate::daysInMonth_data()
327{
328 QTest::addColumn<int>(name: "year");
329 QTest::addColumn<int>(name: "month");
330 QTest::addColumn<int>(name: "day");
331 QTest::addColumn<int>(name: "daysInMonth");
332
333 QTest::newRow(dataTag: "data0") << 0 << 0 << 0 << 0;
334 QTest::newRow(dataTag: "data1") << 2000 << 1 << 1 << 31;
335 QTest::newRow(dataTag: "data2") << 2000 << 2 << 1 << 29;
336 QTest::newRow(dataTag: "data3") << 2000 << 3 << 1 << 31;
337 QTest::newRow(dataTag: "data4") << 2000 << 4 << 1 << 30;
338 QTest::newRow(dataTag: "data5") << 2000 << 5 << 1 << 31;
339 QTest::newRow(dataTag: "data6") << 2000 << 6 << 1 << 30;
340 QTest::newRow(dataTag: "data7") << 2000 << 7 << 1 << 31;
341 QTest::newRow(dataTag: "data8") << 2000 << 8 << 1 << 31;
342 QTest::newRow(dataTag: "data9") << 2000 << 9 << 1 << 30;
343 QTest::newRow(dataTag: "data10") << 2000 << 10 << 1 << 31;
344 QTest::newRow(dataTag: "data11") << 2000 << 11 << 1 << 30;
345 QTest::newRow(dataTag: "data12") << 2000 << 12 << 1 << 31;
346 QTest::newRow(dataTag: "data13") << 2001 << 2 << 1 << 28;
347 QTest::newRow(dataTag: "data14") << 2000 << 0 << 1 << 0;
348}
349
350void tst_QDate::daysInMonth()
351{
352 QFETCH(int, year);
353 QFETCH(int, month);
354 QFETCH(int, day);
355 QFETCH(int, daysInMonth);
356
357 QDate dt(year, month, day);
358 QCOMPARE(dt.daysInMonth(), daysInMonth);
359}
360
361void tst_QDate::daysInYear_data()
362{
363 QTest::addColumn<QDate>(name: "date");
364 QTest::addColumn<int>(name: "expectedDaysInYear");
365
366 QTest::newRow(dataTag: "2000, 1, 1") << QDate(2000, 1, 1) << 366;
367 QTest::newRow(dataTag: "2001, 1, 1") << QDate(2001, 1, 1) << 365;
368 QTest::newRow(dataTag: "4, 1, 1") << QDate(4, 1, 1) << 366;
369 QTest::newRow(dataTag: "5, 1, 1") << QDate(5, 1, 1) << 365;
370 QTest::newRow(dataTag: "0, 0, 0") << QDate(0, 0, 0) << 0;
371}
372
373void tst_QDate::daysInYear()
374{
375 QFETCH(QDate, date);
376 QFETCH(int, expectedDaysInYear);
377
378 QCOMPARE(date.daysInYear(), expectedDaysInYear);
379}
380
381void tst_QDate::getDate()
382{
383 int y, m, d;
384 QDate dt(2000, 1, 1);
385 dt.getDate(year: &y, month: &m, day: &d);
386 QCOMPARE(y, 2000);
387 QCOMPARE(m, 1);
388 QCOMPARE(d, 1);
389 dt.setDate(year: 0, month: 0, day: 0);
390 dt.getDate(year: &y, month: &m, day: &d);
391 QCOMPARE(y, 0);
392 QCOMPARE(m, 0);
393 QCOMPARE(d, 0);
394}
395
396void tst_QDate::weekNumber_data()
397{
398 QTest::addColumn<int>(name: "expectedWeekNum");
399 QTest::addColumn<int>(name: "expectedYearNum");
400 QTest::addColumn<int>(name: "year");
401 QTest::addColumn<int>(name: "month");
402 QTest::addColumn<int>(name: "day");
403
404 enum { Thursday = 4 };
405 bool wasLastYearLong = false; // 1999 was not a long (53-week) year
406 bool isLongYear;
407
408 // full 400-year cycle for Jan 1, 4 and Dec 28, 31
409 for (int yr = 2000; yr < 2400; ++yr, wasLastYearLong = isLongYear) {
410 QByteArray yrstr = QByteArray::number(yr);
411 int wday = QDate(yr, 1, 1).dayOfWeek();
412
413 // the year is 53-week long if Jan 1 is Thursday or, if it's a leap year, a Wednesday
414 isLongYear = (wday == Thursday) || (QDate::isLeapYear(year: yr) && wday == Thursday - 1);
415
416 // Jan 4 is always on week 1
417 QTest::newRow(dataTag: yrstr + "-01-04") << 1 << yr << yr << 1 << 4;
418
419 // Dec 28 is always on the last week
420 QTest::newRow(dataTag: yrstr + "-12-28") << (52 + isLongYear) << yr << yr << 12 << 28;
421
422 // Jan 1 is on either on week 1 or on the last week of the previous year
423 QTest::newRow(dataTag: yrstr + "-01-01")
424 << (wday <= Thursday ? 1 : 52 + wasLastYearLong)
425 << (wday <= Thursday ? yr : yr - 1)
426 << yr << 1 << 1;
427
428 // Dec 31 is either on the last week or week 1 of the next year
429 wday = QDate(yr, 12, 31).dayOfWeek();
430 QTest::newRow(dataTag: yrstr + "-12-31")
431 << (wday >= Thursday ? 52 + isLongYear : 1)
432 << (wday >= Thursday ? yr : yr + 1)
433 << yr << 12 << 31;
434 }
435}
436
437void tst_QDate::weekNumber()
438{
439 int yearNumber;
440 QFETCH( int, year );
441 QFETCH( int, month );
442 QFETCH( int, day );
443 QFETCH( int, expectedWeekNum );
444 QFETCH( int, expectedYearNum );
445 QDate dt1( year, month, day );
446 QCOMPARE( dt1.weekNumber( &yearNumber ), expectedWeekNum );
447 QCOMPARE( yearNumber, expectedYearNum );
448}
449
450void tst_QDate::weekNumber_invalid_data()
451{
452 QTest::addColumn<int>(name: "year");
453 QTest::addColumn<int>(name: "month");
454 QTest::addColumn<int>(name: "day");
455
456 //next we fill it with data
457 QTest::newRow( dataTag: "data0" ) << 0 << 0 << 0;
458 QTest::newRow( dataTag: "data1" ) << 2001 << 1 << 32;
459 QTest::newRow( dataTag: "data2" ) << 1999 << 2 << 29;
460}
461
462void tst_QDate::weekNumber_invalid()
463{
464 QDate dt;
465 int yearNumber;
466 QCOMPARE( dt.weekNumber( &yearNumber ), 0 );
467}
468
469#if QT_CONFIG(timezone)
470void tst_QDate::startOfDay_endOfDay_data()
471{
472 QTest::addColumn<QDate>(name: "date"); // Typically a spring-forward.
473 // A zone in which that date's start and end are worth checking:
474 QTest::addColumn<QByteArray>(name: "zoneName");
475 // The start and end times in that zone:
476 QTest::addColumn<QTime>(name: "start");
477 QTest::addColumn<QTime>(name: "end");
478
479 const QTime initial(0, 0), final(23, 59, 59, 999), invalid(QDateTime().time());
480
481 QTest::newRow(dataTag: "epoch")
482 << QDate(1970, 1, 1) << QByteArray("UTC")
483 << initial << final;
484 QTest::newRow(dataTag: "Brazil")
485 << QDate(2008, 10, 19) << QByteArray("America/Sao_Paulo")
486 << QTime(1, 0) << final;
487#if QT_CONFIG(icu) || !defined(Q_OS_WIN) // MS's TZ APIs lack data
488 QTest::newRow(dataTag: "Sofia")
489 << QDate(1994, 3, 27) << QByteArray("Europe/Sofia")
490 << QTime(1, 0) << final;
491#endif
492 QTest::newRow(dataTag: "Kiritimati")
493 << QDate(1994, 12, 31) << QByteArray("Pacific/Kiritimati")
494 << invalid << invalid;
495 QTest::newRow(dataTag: "Samoa")
496 << QDate(2011, 12, 30) << QByteArray("Pacific/Apia")
497 << invalid << invalid;
498 // TODO: find other zones with transitions at/crossing midnight.
499}
500
501void tst_QDate::startOfDay_endOfDay()
502{
503 QFETCH(QDate, date);
504 QFETCH(QByteArray, zoneName);
505 QFETCH(QTime, start);
506 QFETCH(QTime, end);
507 const QTimeZone zone(zoneName);
508 const bool isSystem = QTimeZone::systemTimeZone() == zone;
509 QDateTime front(date.startOfDay(zone)), back(date.endOfDay(zone));
510 if (end.isValid())
511 QCOMPARE(date.addDays(1).startOfDay(zone).addMSecs(-1), back);
512 if (start.isValid())
513 QCOMPARE(date.addDays(-1).endOfDay(zone).addMSecs(1), front);
514 do { // Avoids duplicating these tests for local-time when it *is* zone:
515 if (start.isValid()) {
516 QCOMPARE(front.date(), date);
517 QCOMPARE(front.time(), start);
518 }
519 if (end.isValid()) {
520 QCOMPARE(back.date(), date);
521 QCOMPARE(back.time(), end);
522 }
523 if (front.timeSpec() == Qt::LocalTime)
524 break;
525 front = date.startOfDay(spec: Qt::LocalTime);
526 back = date.endOfDay(spec: Qt::LocalTime);
527 } while (isSystem);
528 if (end.isValid())
529 QCOMPARE(date.addDays(1).startOfDay(Qt::LocalTime).addMSecs(-1), back);
530 if (start.isValid())
531 QCOMPARE(date.addDays(-1).endOfDay(Qt::LocalTime).addMSecs(1), front);
532 if (!isSystem) {
533 // These might fail if system zone coincides with zone; but only if it
534 // did something similarly unusual on the date picked for this test.
535 if (start.isValid()) {
536 QCOMPARE(front.date(), date);
537 QCOMPARE(front.time(), QTime(0, 0));
538 }
539 if (end.isValid()) {
540 QCOMPARE(back.date(), date);
541 QCOMPARE(back.time(), QTime(23, 59, 59, 999));
542 }
543 }
544}
545#endif // timezone
546
547void tst_QDate::startOfDay_endOfDay_fixed_data()
548{
549 const qint64 kilo(1000);
550 using Bounds = std::numeric_limits<qint64>;
551 const QDateTime
552 first(QDateTime::fromMSecsSinceEpoch(msecs: Bounds::min() + 1, spec: Qt::UTC)),
553 start32sign(QDateTime::fromMSecsSinceEpoch(msecs: -0x80000000L * kilo, spec: Qt::UTC)),
554 end32sign(QDateTime::fromMSecsSinceEpoch(msecs: 0x80000000L * kilo, spec: Qt::UTC)),
555 end32unsign(QDateTime::fromMSecsSinceEpoch(msecs: 0x100000000L * kilo, spec: Qt::UTC)),
556 last(QDateTime::fromMSecsSinceEpoch(msecs: Bounds::max(), spec: Qt::UTC));
557
558 const struct {
559 const char *name;
560 QDate date;
561 } data[] = {
562 { .name: "epoch", .date: QDate(1970, 1, 1) },
563 { .name: "y2k-leap-day", .date: QDate(2000, 2, 29) },
564 // Just outside the start and end of 32-bit time_t:
565 { .name: "pre-sign32", .date: QDate(start32sign.date().year(), 1, 1) },
566 { .name: "post-sign32", .date: QDate(end32sign.date().year(), 12, 31) },
567 { .name: "post-uint32", .date: QDate(end32unsign.date().year(), 12, 31) },
568 // Just inside the start and end of QDateTime's range:
569 { .name: "first-full", .date: first.date().addDays(days: 1) },
570 { .name: "last-full", .date: last.date().addDays(days: -1) }
571 };
572
573 QTest::addColumn<QDate>(name: "date");
574 for (const auto &r : data)
575 QTest::newRow(dataTag: r.name) << r.date;
576}
577
578void tst_QDate::startOfDay_endOfDay_fixed()
579{
580 const QTime early(0, 0), late(23, 59, 59, 999);
581 QFETCH(QDate, date);
582
583 QDateTime start(date.startOfDay(spec: Qt::UTC));
584 QDateTime end(date.endOfDay(spec: Qt::UTC));
585 QCOMPARE(start.date(), date);
586 QCOMPARE(end.date(), date);
587 QCOMPARE(start.time(), early);
588 QCOMPARE(end.time(), late);
589 QCOMPARE(date.addDays(1).startOfDay(Qt::UTC).addMSecs(-1), end);
590 QCOMPARE(date.addDays(-1).endOfDay(Qt::UTC).addMSecs(1), start);
591 for (int offset = -60 * 16; offset <= 60 * 16; offset += 65) {
592 start = date.startOfDay(spec: Qt::OffsetFromUTC, offsetSeconds: offset);
593 end = date.endOfDay(spec: Qt::OffsetFromUTC, offsetSeconds: offset);
594 QCOMPARE(start.date(), date);
595 QCOMPARE(end.date(), date);
596 QCOMPARE(start.time(), early);
597 QCOMPARE(end.time(), late);
598 QCOMPARE(date.addDays(1).startOfDay(Qt::OffsetFromUTC, offset).addMSecs(-1), end);
599 QCOMPARE(date.addDays(-1).endOfDay(Qt::OffsetFromUTC, offset).addMSecs(1), start);
600 }
601}
602
603void tst_QDate::startOfDay_endOfDay_bounds()
604{
605 // Check the days in which QDateTime's range starts and ends:
606 using Bounds = std::numeric_limits<qint64>;
607 const QDateTime
608 first(QDateTime::fromMSecsSinceEpoch(msecs: Bounds::min(), spec: Qt::UTC)),
609 last(QDateTime::fromMSecsSinceEpoch(msecs: Bounds::max(), spec: Qt::UTC)),
610 epoch(QDateTime::fromMSecsSinceEpoch(msecs: 0, spec: Qt::UTC));
611 // First, check these *are* the start and end of QDateTime's range:
612 QVERIFY(first.isValid());
613 QVERIFY(last.isValid());
614 QVERIFY(first < epoch);
615 QVERIFY(last > epoch);
616 // QDateTime's addMSecs doesn't check against {und,ov}erflow ...
617 QVERIFY(!first.addMSecs(-1).isValid() || first.addMSecs(-1) > first);
618 QVERIFY(!last.addMSecs(1).isValid() || last.addMSecs(1) < last);
619
620 // Now test start/end methods with them:
621 QCOMPARE(first.date().endOfDay(Qt::UTC).time(), QTime(23, 59, 59, 999));
622 QCOMPARE(last.date().startOfDay(Qt::UTC).time(), QTime(0, 0));
623 QVERIFY(!first.date().startOfDay(Qt::UTC).isValid());
624 QVERIFY(!last.date().endOfDay(Qt::UTC).isValid());
625}
626
627void tst_QDate::julianDaysLimits()
628{
629 qint64 min = std::numeric_limits<qint64>::min();
630 qint64 max = std::numeric_limits<qint64>::max();
631 qint64 minJd = Q_INT64_C(-784350574879);
632 qint64 maxJd = Q_INT64_C( 784354017364);
633
634 QDate maxDate = QDate::fromJulianDay(jd_: maxJd);
635 QDate minDate = QDate::fromJulianDay(jd_: minJd);
636 QDate zeroDate = QDate::fromJulianDay(jd_: 0);
637
638 QDate dt = QDate::fromJulianDay(jd_: min);
639 QCOMPARE(dt.isValid(), false);
640 dt = QDate::fromJulianDay(jd_: minJd - 1);
641 QCOMPARE(dt.isValid(), false);
642 dt = QDate::fromJulianDay(jd_: minJd);
643 QCOMPARE(dt.isValid(), true);
644 dt = QDate::fromJulianDay(jd_: minJd + 1);
645 QCOMPARE(dt.isValid(), true);
646 dt = QDate::fromJulianDay(jd_: maxJd - 1);
647 QCOMPARE(dt.isValid(), true);
648 dt = QDate::fromJulianDay(jd_: maxJd);
649 QCOMPARE(dt.isValid(), true);
650 dt = QDate::fromJulianDay(jd_: maxJd + 1);
651 QCOMPARE(dt.isValid(), false);
652 dt = QDate::fromJulianDay(jd_: max);
653 QCOMPARE(dt.isValid(), false);
654
655 dt = maxDate.addDays(days: 1);
656 QCOMPARE(dt.isValid(), false);
657 dt = maxDate.addDays(days: 0);
658 QCOMPARE(dt.isValid(), true);
659 dt = maxDate.addDays(days: -1);
660 QCOMPARE(dt.isValid(), true);
661 dt = maxDate.addDays(days: max);
662 QCOMPARE(dt.isValid(), false);
663 dt = maxDate.addDays(days: min);
664 QCOMPARE(dt.isValid(), false);
665
666 dt = minDate.addDays(days: -1);
667 QCOMPARE(dt.isValid(), false);
668 dt = minDate.addDays(days: 0);
669 QCOMPARE(dt.isValid(), true);
670 dt = minDate.addDays(days: 1);
671 QCOMPARE(dt.isValid(), true);
672 dt = minDate.addDays(days: min);
673 QCOMPARE(dt.isValid(), false);
674 dt = minDate.addDays(days: max);
675 QCOMPARE(dt.isValid(), false);
676
677 dt = zeroDate.addDays(days: -1);
678 QCOMPARE(dt.isValid(), true);
679 dt = zeroDate.addDays(days: 0);
680 QCOMPARE(dt.isValid(), true);
681 dt = zeroDate.addDays(days: 1);
682 QCOMPARE(dt.isValid(), true);
683 dt = zeroDate.addDays(days: min);
684 QCOMPARE(dt.isValid(), false);
685 dt = zeroDate.addDays(days: max);
686 QCOMPARE(dt.isValid(), false);
687}
688
689void tst_QDate::addDays()
690{
691 QFETCH( int, year );
692 QFETCH( int, month );
693 QFETCH( int, day );
694 QFETCH( int, amountToAdd );
695 QFETCH( int, expectedYear );
696 QFETCH( int, expectedMonth );
697 QFETCH( int, expectedDay );
698
699 QDate dt( year, month, day );
700 dt = dt.addDays( days: amountToAdd );
701
702 QCOMPARE( dt.year(), expectedYear );
703 QCOMPARE( dt.month(), expectedMonth );
704 QCOMPARE( dt.day(), expectedDay );
705}
706
707void tst_QDate::addDays_data()
708{
709 QTest::addColumn<int>(name: "year");
710 QTest::addColumn<int>(name: "month");
711 QTest::addColumn<int>(name: "day");
712 QTest::addColumn<int>(name: "amountToAdd");
713 QTest::addColumn<int>(name: "expectedYear");
714 QTest::addColumn<int>(name: "expectedMonth");
715 QTest::addColumn<int>(name: "expectedDay");
716
717 QTest::newRow( dataTag: "data0" ) << 2000 << 1 << 1 << 1 << 2000 << 1 << 2;
718 QTest::newRow( dataTag: "data1" ) << 2000 << 1 << 31 << 1 << 2000 << 2 << 1;
719 QTest::newRow( dataTag: "data2" ) << 2000 << 2 << 28 << 1 << 2000 << 2 << 29;
720 QTest::newRow( dataTag: "data3" ) << 2000 << 2 << 29 << 1 << 2000 << 3 << 1;
721 QTest::newRow( dataTag: "data4" ) << 2000 << 12 << 31 << 1 << 2001 << 1 << 1;
722 QTest::newRow( dataTag: "data5" ) << 2001 << 2 << 28 << 1 << 2001 << 3 << 1;
723 QTest::newRow( dataTag: "data6" ) << 2001 << 2 << 28 << 30 << 2001 << 3 << 30;
724 QTest::newRow( dataTag: "data7" ) << 2001 << 3 << 30 << 5 << 2001 << 4 << 4;
725
726 QTest::newRow( dataTag: "data8" ) << 2000 << 1 << 1 << -1 << 1999 << 12 << 31;
727 QTest::newRow( dataTag: "data9" ) << 2000 << 1 << 31 << -1 << 2000 << 1 << 30;
728 QTest::newRow( dataTag: "data10" ) << 2000 << 2 << 28 << -1 << 2000 << 2 << 27;
729 QTest::newRow( dataTag: "data11" ) << 2001 << 2 << 28 << -30 << 2001 << 1 << 29;
730
731 QTest::newRow( dataTag: "data12" ) << -4713 << 1 << 2 << -2 << -4714 << 12 << 31;
732 QTest::newRow( dataTag: "data13" ) << -4713 << 1 << 2 << 2 << -4713 << 1 << 4;
733
734 QTest::newRow( dataTag: "invalid" ) << 0 << 0 << 0 << 1 << 0 << 0 << 0;
735}
736
737void tst_QDate::addMonths()
738{
739 QFETCH( int, year );
740 QFETCH( int, month );
741 QFETCH( int, day );
742 QFETCH( int, amountToAdd );
743 QFETCH( int, expectedYear );
744 QFETCH( int, expectedMonth );
745 QFETCH( int, expectedDay );
746
747 QDate dt( year, month, day );
748 dt = dt.addMonths( months: amountToAdd );
749
750 QCOMPARE( dt.year(), expectedYear );
751 QCOMPARE( dt.month(), expectedMonth );
752 QCOMPARE( dt.day(), expectedDay );
753}
754
755void tst_QDate::addMonths_data()
756{
757 QTest::addColumn<int>(name: "year");
758 QTest::addColumn<int>(name: "month");
759 QTest::addColumn<int>(name: "day");
760 QTest::addColumn<int>(name: "amountToAdd");
761 QTest::addColumn<int>(name: "expectedYear");
762 QTest::addColumn<int>(name: "expectedMonth");
763 QTest::addColumn<int>(name: "expectedDay");
764
765 QTest::newRow( dataTag: "data0" ) << 2000 << 1 << 1 << 1 << 2000 << 2 << 1;
766 QTest::newRow( dataTag: "data1" ) << 2000 << 1 << 31 << 1 << 2000 << 2 << 29;
767 QTest::newRow( dataTag: "data2" ) << 2000 << 2 << 28 << 1 << 2000 << 3 << 28;
768 QTest::newRow( dataTag: "data3" ) << 2000 << 2 << 29 << 1 << 2000 << 3 << 29;
769 QTest::newRow( dataTag: "data4" ) << 2000 << 12 << 31 << 1 << 2001 << 1 << 31;
770 QTest::newRow( dataTag: "data5" ) << 2001 << 2 << 28 << 1 << 2001 << 3 << 28;
771 QTest::newRow( dataTag: "data6" ) << 2001 << 2 << 28 << 12 << 2002 << 2 << 28;
772 QTest::newRow( dataTag: "data7" ) << 2000 << 2 << 29 << 12 << 2001 << 2 << 28;
773 QTest::newRow( dataTag: "data8" ) << 2000 << 10 << 15 << 4 << 2001 << 2 << 15;
774
775 QTest::newRow( dataTag: "data9" ) << 2000 << 1 << 1 << -1 << 1999 << 12 << 1;
776 QTest::newRow( dataTag: "data10" ) << 2000 << 1 << 31 << -1 << 1999 << 12 << 31;
777 QTest::newRow( dataTag: "data11" ) << 2000 << 12 << 31 << -1 << 2000 << 11 << 30;
778 QTest::newRow( dataTag: "data12" ) << 2001 << 2 << 28 << -12 << 2000 << 2 << 28;
779 QTest::newRow( dataTag: "data13" ) << 2000 << 1 << 31 << -7 << 1999 << 6 << 30;
780 QTest::newRow( dataTag: "data14" ) << 2000 << 2 << 29 << -12 << 1999 << 2 << 28;
781
782 // year sign change:
783 QTest::newRow( dataTag: "data15" ) << 1 << 1 << 1 << -1 << -1 << 12 << 1;
784 QTest::newRow( dataTag: "data16" ) << 1 << 1 << 1 << -12 << -1 << 1 << 1;
785 QTest::newRow( dataTag: "data17" ) << -1 << 12 << 1 << 1 << 1 << 1 << 1;
786 QTest::newRow( dataTag: "data18" ) << -1 << 1 << 1 << 12 << 1 << 1 << 1;
787 QTest::newRow( dataTag: "data19" ) << -2 << 1 << 1 << 12 << -1 << 1 << 1;
788
789 QTest::newRow( dataTag: "invalid" ) << 0 << 0 << 0 << 1 << 0 << 0 << 0;
790}
791
792void tst_QDate::addYears()
793{
794 QFETCH( int, year );
795 QFETCH( int, month );
796 QFETCH( int, day );
797 QFETCH( int, amountToAdd );
798 QFETCH( int, expectedYear );
799 QFETCH( int, expectedMonth );
800 QFETCH( int, expectedDay );
801
802 QDate dt( year, month, day );
803 dt = dt.addYears( years: amountToAdd );
804
805 QCOMPARE( dt.year(), expectedYear );
806 QCOMPARE( dt.month(), expectedMonth );
807 QCOMPARE( dt.day(), expectedDay );
808}
809
810void tst_QDate::addYears_data()
811{
812 QTest::addColumn<int>(name: "year");
813 QTest::addColumn<int>(name: "month");
814 QTest::addColumn<int>(name: "day");
815 QTest::addColumn<int>(name: "amountToAdd");
816 QTest::addColumn<int>(name: "expectedYear");
817 QTest::addColumn<int>(name: "expectedMonth");
818 QTest::addColumn<int>(name: "expectedDay");
819
820 QTest::newRow( dataTag: "data0" ) << 2000 << 1 << 1 << 1 << 2001 << 1 << 1;
821 QTest::newRow( dataTag: "data1" ) << 2000 << 1 << 31 << 1 << 2001 << 1 << 31;
822 QTest::newRow( dataTag: "data2" ) << 2000 << 2 << 28 << 1 << 2001 << 2 << 28;
823 QTest::newRow( dataTag: "data3" ) << 2000 << 2 << 29 << 1 << 2001 << 2 << 28;
824 QTest::newRow( dataTag: "data4" ) << 2000 << 12 << 31 << 1 << 2001 << 12 << 31;
825 QTest::newRow( dataTag: "data5" ) << 2001 << 2 << 28 << 3 << 2004 << 2 << 28;
826 QTest::newRow( dataTag: "data6" ) << 2000 << 2 << 29 << 4 << 2004 << 2 << 29;
827
828 QTest::newRow( dataTag: "data7" ) << 2000 << 1 << 31 << -1 << 1999 << 1 << 31;
829 QTest::newRow( dataTag: "data9" ) << 2000 << 2 << 29 << -1 << 1999 << 2 << 28;
830 QTest::newRow( dataTag: "data10" ) << 2000 << 12 << 31 << -1 << 1999 << 12 << 31;
831 QTest::newRow( dataTag: "data11" ) << 2001 << 2 << 28 << -3 << 1998 << 2 << 28;
832 QTest::newRow( dataTag: "data12" ) << 2000 << 2 << 29 << -4 << 1996 << 2 << 29;
833 QTest::newRow( dataTag: "data13" ) << 2000 << 2 << 29 << -5 << 1995 << 2 << 28;
834
835 QTest::newRow( dataTag: "data14" ) << 2000 << 1 << 1 << -1999 << 1 << 1 << 1;
836 QTest::newRow( dataTag: "data15" ) << 2000 << 1 << 1 << -2000 << -1 << 1 << 1;
837 QTest::newRow( dataTag: "data16" ) << 2000 << 1 << 1 << -2001 << -2 << 1 << 1;
838 QTest::newRow( dataTag: "data17" ) << -2000 << 1 << 1 << 1999 << -1 << 1 << 1;
839 QTest::newRow( dataTag: "data18" ) << -2000 << 1 << 1 << 2000 << 1 << 1 << 1;
840 QTest::newRow( dataTag: "data19" ) << -2000 << 1 << 1 << 2001 << 2 << 1 << 1;
841
842 QTest::newRow( dataTag: "invalid" ) << 0 << 0 << 0 << 1 << 0 << 0 << 0;
843}
844
845void tst_QDate::daysTo()
846{
847 qint64 minJd = Q_INT64_C(-784350574879);
848 qint64 maxJd = Q_INT64_C( 784354017364);
849
850 QDate dt1(2000, 1, 1);
851 QDate dt2(2000, 1, 5);
852 QCOMPARE(dt1.daysTo(dt2), (qint64) 4);
853 QCOMPARE(dt2.daysTo(dt1), (qint64) -4);
854
855 dt1.setDate(year: 0, month: 0, day: 0);
856 QCOMPARE(dt1.daysTo(dt2), (qint64) 0);
857 dt1.setDate(year: 2000, month: 1, day: 1);
858 dt2.setDate(year: 0, month: 0, day: 0);
859 QCOMPARE(dt1.daysTo(dt2), (qint64) 0);
860
861
862 QDate maxDate = QDate::fromJulianDay(jd_: maxJd);
863 QDate minDate = QDate::fromJulianDay(jd_: minJd);
864 QDate zeroDate = QDate::fromJulianDay(jd_: 0);
865
866 QCOMPARE(maxDate.daysTo(minDate), minJd - maxJd);
867 QCOMPARE(minDate.daysTo(maxDate), maxJd - minJd);
868 QCOMPARE(maxDate.daysTo(zeroDate), -maxJd);
869 QCOMPARE(zeroDate.daysTo(maxDate), maxJd);
870 QCOMPARE(minDate.daysTo(zeroDate), -minJd);
871 QCOMPARE(zeroDate.daysTo(minDate), minJd);
872}
873
874void tst_QDate::operator_eq_eq_data()
875{
876 QTest::addColumn<QDate>(name: "d1");
877 QTest::addColumn<QDate>(name: "d2");
878 QTest::addColumn<bool>(name: "expectEqual");
879
880 QTest::newRow(dataTag: "data0") << QDate(2000,1,2) << QDate(2000,1,2) << true;
881 QTest::newRow(dataTag: "data1") << QDate(2001,12,5) << QDate(2001,12,5) << true;
882 QTest::newRow(dataTag: "data2") << QDate(2001,12,5) << QDate(2001,12,5) << true;
883 QTest::newRow(dataTag: "data3") << QDate(2001,12,5) << QDate(2002,12,5) << false;
884
885 QDate date1(1900, 1, 1);
886 QDate date2 = date1.addDays(days: 1);
887 QDate date3 = date1.addDays(days: -1);
888 QDate date4 = date1.addMonths(months: 1);
889 QDate date5 = date1.addMonths(months: -1);
890 QDate date6 = date1.addYears(years: 1);
891 QDate date7 = date1.addYears(years: -1);
892
893 QTest::newRow(dataTag: "data4") << date2 << date3 << false;
894 QTest::newRow(dataTag: "data5") << date4 << date5 << false;
895 QTest::newRow(dataTag: "data6") << date6 << date7 << false;
896 QTest::newRow(dataTag: "data7") << date1 << date2 << false;
897 QTest::newRow(dataTag: "data8") << date1 << date3 << false;
898 QTest::newRow(dataTag: "data9") << date1 << date4 << false;
899 QTest::newRow(dataTag: "data10") << date1 << date5 << false;
900 QTest::newRow(dataTag: "data11") << date1 << date6 << false;
901 QTest::newRow(dataTag: "data12") << date1 << date7 << false;
902}
903
904void tst_QDate::operator_eq_eq()
905{
906 QFETCH(QDate, d1);
907 QFETCH(QDate, d2);
908 QFETCH(bool, expectEqual);
909
910 bool equal = d1 == d2;
911 QCOMPARE(equal, expectEqual);
912 bool notEqual = d1 != d2;
913 QCOMPARE(notEqual, !expectEqual);
914
915 if (equal)
916 QVERIFY(qHash(d1) == qHash(d2));
917}
918
919void tst_QDate::operator_lt()
920{
921 QDate d1(2000,1,2);
922 QDate d2(2000,1,2);
923 QVERIFY( !(d1 < d2) );
924
925 d1 = QDate(2001,12,4);
926 d2 = QDate(2001,12,5);
927 QVERIFY( d1 < d2 );
928
929 d1 = QDate(2001,11,5);
930 d2 = QDate(2001,12,5);
931 QVERIFY( d1 < d2 );
932
933 d1 = QDate(2000,12,5);
934 d2 = QDate(2001,12,5);
935 QVERIFY( d1 < d2 );
936
937 d1 = QDate(2002,12,5);
938 d2 = QDate(2001,12,5);
939 QVERIFY( !(d1 < d2) );
940
941 d1 = QDate(2001,12,5);
942 d2 = QDate(2001,11,5);
943 QVERIFY( !(d1 < d2) );
944
945 d1 = QDate(2001,12,6);
946 d2 = QDate(2001,12,5);
947 QVERIFY( !(d1 < d2) );
948}
949
950void tst_QDate::operator_gt()
951{
952 QDate d1(2000,1,2);
953 QDate d2(2000,1,2);
954 QVERIFY( !(d1 > d2) );
955
956 d1 = QDate(2001,12,4);
957 d2 = QDate(2001,12,5);
958 QVERIFY( !(d1 > d2) );
959
960 d1 = QDate(2001,11,5);
961 d2 = QDate(2001,12,5);
962 QVERIFY( !(d1 > d2) );
963
964 d1 = QDate(2000,12,5);
965 d2 = QDate(2001,12,5);
966 QVERIFY( !(d1 > d2) );
967
968 d1 = QDate(2002,12,5);
969 d2 = QDate(2001,12,5);
970 QVERIFY( d1 > d2 );
971
972 d1 = QDate(2001,12,5);
973 d2 = QDate(2001,11,5);
974 QVERIFY( d1 > d2 );
975
976 d1 = QDate(2001,12,6);
977 d2 = QDate(2001,12,5);
978 QVERIFY( d1 > d2 );
979}
980
981void tst_QDate::operator_lt_eq()
982{
983 QDate d1(2000,1,2);
984 QDate d2(2000,1,2);
985 QVERIFY( d1 <= d2 );
986
987 d1 = QDate(2001,12,4);
988 d2 = QDate(2001,12,5);
989 QVERIFY( d1 <= d2 );
990
991 d1 = QDate(2001,11,5);
992 d2 = QDate(2001,12,5);
993 QVERIFY( d1 <= d2 );
994
995 d1 = QDate(2000,12,5);
996 d2 = QDate(2001,12,5);
997 QVERIFY( d1 <= d2 );
998
999 d1 = QDate(2002,12,5);
1000 d2 = QDate(2001,12,5);
1001 QVERIFY( !(d1 <= d2) );
1002
1003 d1 = QDate(2001,12,5);
1004 d2 = QDate(2001,11,5);
1005 QVERIFY( !(d1 <= d2) );
1006
1007 d1 = QDate(2001,12,6);
1008 d2 = QDate(2001,12,5);
1009 QVERIFY( !(d1 <= d2) );
1010}
1011
1012void tst_QDate::operator_gt_eq()
1013{
1014 QDate d1(2000,1,2);
1015 QDate d2(2000,1,2);
1016 QVERIFY( d1 >= d2 );
1017
1018 d1 = QDate(2001,12,4);
1019 d2 = QDate(2001,12,5);
1020 QVERIFY( !(d1 >= d2) );
1021
1022 d1 = QDate(2001,11,5);
1023 d2 = QDate(2001,12,5);
1024 QVERIFY( !(d1 >= d2) );
1025
1026 d1 = QDate(2000,12,5);
1027 d2 = QDate(2001,12,5);
1028 QVERIFY( !(d1 >= d2) );
1029
1030 d1 = QDate(2002,12,5);
1031 d2 = QDate(2001,12,5);
1032 QVERIFY( d1 >= d2 );
1033
1034 d1 = QDate(2001,12,5);
1035 d2 = QDate(2001,11,5);
1036 QVERIFY( d1 >= d2 );
1037
1038 d1 = QDate(2001,12,6);
1039 d2 = QDate(2001,12,5);
1040 QVERIFY( d1 >= d2 );
1041}
1042
1043Q_DECLARE_METATYPE(QDataStream::Version)
1044
1045void tst_QDate::operator_insert_extract_data()
1046{
1047 QTest::addColumn<QDate>(name: "date");
1048 QTest::addColumn<QDataStream::Version>(name: "dataStreamVersion");
1049
1050 QMap<QDataStream::Version, QString> versionsToTest;
1051 versionsToTest.insert(akey: QDataStream::Qt_1_0, avalue: QString::fromLatin1(str: "Qt_1_0"));
1052 versionsToTest.insert(akey: QDataStream::Qt_2_0, avalue: QString::fromLatin1(str: "Qt_2_0"));
1053 versionsToTest.insert(akey: QDataStream::Qt_2_1, avalue: QString::fromLatin1(str: "Qt_2_1"));
1054 versionsToTest.insert(akey: QDataStream::Qt_3_0, avalue: QString::fromLatin1(str: "Qt_3_0"));
1055 versionsToTest.insert(akey: QDataStream::Qt_3_1, avalue: QString::fromLatin1(str: "Qt_3_1"));
1056 versionsToTest.insert(akey: QDataStream::Qt_3_3, avalue: QString::fromLatin1(str: "Qt_3_3"));
1057 versionsToTest.insert(akey: QDataStream::Qt_4_0, avalue: QString::fromLatin1(str: "Qt_4_0"));
1058 versionsToTest.insert(akey: QDataStream::Qt_4_1, avalue: QString::fromLatin1(str: "Qt_4_1"));
1059 versionsToTest.insert(akey: QDataStream::Qt_4_2, avalue: QString::fromLatin1(str: "Qt_4_2"));
1060 versionsToTest.insert(akey: QDataStream::Qt_4_3, avalue: QString::fromLatin1(str: "Qt_4_3"));
1061 versionsToTest.insert(akey: QDataStream::Qt_4_4, avalue: QString::fromLatin1(str: "Qt_4_4"));
1062 versionsToTest.insert(akey: QDataStream::Qt_4_5, avalue: QString::fromLatin1(str: "Qt_4_5"));
1063 versionsToTest.insert(akey: QDataStream::Qt_4_6, avalue: QString::fromLatin1(str: "Qt_4_6"));
1064 versionsToTest.insert(akey: QDataStream::Qt_4_7, avalue: QString::fromLatin1(str: "Qt_4_7"));
1065 versionsToTest.insert(akey: QDataStream::Qt_4_8, avalue: QString::fromLatin1(str: "Qt_4_8"));
1066 versionsToTest.insert(akey: QDataStream::Qt_4_9, avalue: QString::fromLatin1(str: "Qt_4_9"));
1067 versionsToTest.insert(akey: QDataStream::Qt_5_0, avalue: QString::fromLatin1(str: "Qt_5_0"));
1068
1069 for (QMap<QDataStream::Version, QString>::ConstIterator it = versionsToTest.constBegin();
1070 it != versionsToTest.constEnd(); ++it) {
1071 const QString &version(it.value());
1072 QTest::newRow(dataTag: ("(invalid) " + version).toLocal8Bit().constData()) << invalidDate() << it.key();
1073 QTest::newRow(dataTag: ("(1, 1, 1) " + version).toLocal8Bit().constData()) << QDate(1, 1, 1) << it.key();
1074 QTest::newRow(dataTag: ("(-1, 1, 1) " + version).toLocal8Bit().constData()) << QDate(-1, 1, 1) << it.key();
1075 QTest::newRow(dataTag: ("(1995, 5, 20) " + version).toLocal8Bit().constData()) << QDate(1995, 5, 20) << it.key();
1076
1077 // Test minimums for quint32/qint64.
1078 if (it.key() >= QDataStream::Qt_5_0)
1079 QTest::newRow(dataTag: ("(-4714, 11, 24) " + version).toLocal8Bit().constData()) << QDate(-4714, 11, 24) << it.key();
1080 else
1081 QTest::newRow(dataTag: ("(-4713, 1, 2) " + version).toLocal8Bit().constData()) << QDate(-4713, 1, 2) << it.key();
1082 }
1083}
1084
1085void tst_QDate::operator_insert_extract()
1086{
1087 QFETCH(QDate, date);
1088 QFETCH(QDataStream::Version, dataStreamVersion);
1089
1090 QByteArray byteArray;
1091 QDataStream dataStream(&byteArray, QIODevice::ReadWrite);
1092 dataStream.setVersion(dataStreamVersion);
1093 dataStream << date;
1094 dataStream.device()->reset();
1095 QDate deserialised;
1096 dataStream >> deserialised;
1097 QCOMPARE(dataStream.status(), QDataStream::Ok);
1098
1099 QCOMPARE(deserialised, date);
1100}
1101
1102void tst_QDate::fromStringDateFormat_data()
1103{
1104 QTest::addColumn<QString>(name: "dateStr");
1105 QTest::addColumn<Qt::DateFormat>(name: "dateFormat");
1106 QTest::addColumn<QDate>(name: "expectedDate");
1107
1108 QTest::newRow(dataTag: "text0") << QString("Sat May 20 1995") << Qt::TextDate << QDate(1995, 5, 20);
1109 QTest::newRow(dataTag: "text1") << QString("Tue Dec 17 2002") << Qt::TextDate << QDate(2002, 12, 17);
1110 QTest::newRow(dataTag: "text2") << QDate(1999, 11, 14).toString(format: Qt::TextDate) << Qt::TextDate << QDate(1999, 11, 14);
1111 QTest::newRow(dataTag: "text3") << QString("xxx Jan 1 0999") << Qt::TextDate << QDate(999, 1, 1);
1112 QTest::newRow(dataTag: "text3b") << QString("xxx Jan 1 999") << Qt::TextDate << QDate(999, 1, 1);
1113 QTest::newRow(dataTag: "text4") << QString("xxx Jan 1 12345") << Qt::TextDate << QDate(12345, 1, 1);
1114 QTest::newRow(dataTag: "text5") << QString("xxx Jan 1 -0001") << Qt::TextDate << QDate(-1, 1, 1);
1115 QTest::newRow(dataTag: "text6") << QString("xxx Jan 1 -4712") << Qt::TextDate << QDate(-4712, 1, 1);
1116 QTest::newRow(dataTag: "text7") << QString("xxx Nov 25 -4713") << Qt::TextDate << QDate(-4713, 11, 25);
1117 QTest::newRow(dataTag: "text, empty") << QString() << Qt::TextDate << QDate();
1118 QTest::newRow(dataTag: "text, 3 part") << QString("part1 part2 part3") << Qt::TextDate << QDate();
1119 QTest::newRow(dataTag: "text, invalid month name") << QString("Wed BabytownFrolics 8 2012") << Qt::TextDate << QDate();
1120 QTest::newRow(dataTag: "text, invalid day") << QString("Wed May Wilhelm 2012") << Qt::TextDate << QDate();
1121 QTest::newRow(dataTag: "text, invalid year") << QString("Wed May 8 Cats") << Qt::TextDate << QDate();
1122
1123 QTest::newRow(dataTag: "iso0") << QString("1995-05-20") << Qt::ISODate << QDate(1995, 5, 20);
1124 QTest::newRow(dataTag: "iso1") << QString("2002-12-17") << Qt::ISODate << QDate(2002, 12, 17);
1125 QTest::newRow(dataTag: "iso2") << QDate(1999, 11, 14).toString(format: Qt::ISODate) << Qt::ISODate << QDate(1999, 11, 14);
1126 QTest::newRow(dataTag: "iso3") << QString("0999-01-01") << Qt::ISODate << QDate(999, 1, 1);
1127 QTest::newRow(dataTag: "iso3b") << QString("0999-01-01") << Qt::ISODate << QDate(999, 1, 1);
1128 QTest::newRow(dataTag: "iso4") << QString("2000101101") << Qt::ISODate << QDate();
1129 QTest::newRow(dataTag: "iso5") << QString("2000/01/01") << Qt::ISODate << QDate(2000, 1, 1);
1130 QTest::newRow(dataTag: "iso6") << QString("2000-01-01 blah") << Qt::ISODate << QDate(2000, 1, 1);
1131 QTest::newRow(dataTag: "iso7") << QString("2000-01-011blah") << Qt::ISODate << QDate();
1132 QTest::newRow(dataTag: "iso8") << QString("2000-01-01blah") << Qt::ISODate << QDate(2000, 1, 1);
1133 QTest::newRow(dataTag: "iso9") << QString("-001-01-01") << Qt::ISODate << QDate();
1134 QTest::newRow(dataTag: "iso10") << QString("99999-01-01") << Qt::ISODate << QDate();
1135
1136 // Test Qt::RFC2822Date format (RFC 2822).
1137 QTest::newRow(dataTag: "RFC 2822") << QString::fromLatin1(str: "13 Feb 1987 13:24:51 +0100")
1138 << Qt::RFC2822Date << QDate(1987, 2, 13);
1139 QTest::newRow(dataTag: "RFC 2822 after space")
1140 << QString::fromLatin1(str: " 13 Feb 1987 13:24:51 +0100")
1141 << Qt::RFC2822Date << QDate(1987, 2, 13);
1142 QTest::newRow(dataTag: "RFC 2822 with day") << QString::fromLatin1(str: "Thu, 01 Jan 1970 00:12:34 +0000")
1143 << Qt::RFC2822Date << QDate(1970, 1, 1);
1144 QTest::newRow(dataTag: "RFC 2822 with day after space")
1145 << QString::fromLatin1(str: " Thu, 01 Jan 1970 00:12:34 +0000")
1146 << Qt::RFC2822Date << QDate(1970, 1, 1);
1147 // No timezone
1148 QTest::newRow(dataTag: "RFC 2822 no timezone") << QString::fromLatin1(str: "01 Jan 1970 00:12:34")
1149 << Qt::RFC2822Date << QDate(1970, 1, 1);
1150 // No time specified
1151 QTest::newRow(dataTag: "RFC 2822 date only") << QString::fromLatin1(str: "01 Nov 2002")
1152 << Qt::RFC2822Date << QDate(2002, 11, 1);
1153 QTest::newRow(dataTag: "RFC 2822 with day date only") << QString::fromLatin1(str: "Fri, 01 Nov 2002")
1154 << Qt::RFC2822Date << QDate(2002, 11, 1);
1155 // Test invalid month, day, year
1156 QTest::newRow(dataTag: "RFC 2822 invalid month name") << QString::fromLatin1(str: "13 Fev 1987 13:24:51 +0100")
1157 << Qt::RFC2822Date << QDate();
1158 QTest::newRow(dataTag: "RFC 2822 invalid day") << QString::fromLatin1(str: "36 Fev 1987 13:24:51 +0100")
1159 << Qt::RFC2822Date << QDate();
1160 QTest::newRow(dataTag: "RFC 2822 invalid year") << QString::fromLatin1(str: "13 Fev 0000 13:24:51 +0100")
1161 << Qt::RFC2822Date << QDate();
1162 // Test invalid characters (currently ignoring trailing junk, but see QTBUG-80038).
1163 QTest::newRow(dataTag: "RFC 2822 invalid character at end")
1164 << QString::fromLatin1(str: "01 Jan 2012 08:00:00 +0100!")
1165 << Qt::RFC2822Date << QDate(2012, 1, 1);
1166 QTest::newRow(dataTag: "RFC 2822 invalid character at front")
1167 << QString::fromLatin1(str: "!01 Jan 2012 08:00:00 +0100") << Qt::RFC2822Date << QDate();
1168 QTest::newRow(dataTag: "RFC 2822 invalid character both ends")
1169 << QString::fromLatin1(str: "!01 Jan 2012 08:00:00 +0100!") << Qt::RFC2822Date << QDate();
1170 QTest::newRow(dataTag: "RFC 2822 invalid character at front, 2 at back")
1171 << QString::fromLatin1(str: "!01 Jan 2012 08:00:00 +0100..") << Qt::RFC2822Date << QDate();
1172 QTest::newRow(dataTag: "RFC 2822 invalid character 2 at front")
1173 << QString::fromLatin1(str: "!!01 Jan 2012 08:00:00 +0100") << Qt::RFC2822Date << QDate();
1174 // The common date text used by the "invalid character" tests, just to be
1175 // sure *it's* not what's invalid:
1176 QTest::newRow(dataTag: "RFC 2822 (not invalid)")
1177 << QString::fromLatin1(str: "01 Jan 2012 08:00:00 +0100")
1178 << Qt::RFC2822Date << QDate(2012, 1, 1);
1179
1180 // Test Qt::RFC2822Date format (RFC 850 and 1036, permissive).
1181 QTest::newRow(dataTag: "RFC 850 and 1036") << QString::fromLatin1(str: "Fri Feb 13 13:24:51 1987 +0100")
1182 << Qt::RFC2822Date << QDate(1987, 2, 13);
1183 QTest::newRow(dataTag: "RFC 850 and 1036 after space")
1184 << QString::fromLatin1(str: " Fri Feb 13 13:24:51 1987 +0100")
1185 << Qt::RFC2822Date << QDate(1987, 2, 13);
1186 // No timezone
1187 QTest::newRow(dataTag: "RFC 850 and 1036 no timezone") << QString::fromLatin1(str: "Thu Jan 01 00:12:34 1970")
1188 << Qt::RFC2822Date << QDate(1970, 1, 1);
1189 // No time specified
1190 QTest::newRow(dataTag: "RFC 850 and 1036 date only") << QString::fromLatin1(str: "Fri Nov 01 2002")
1191 << Qt::RFC2822Date << QDate(2002, 11, 1);
1192 // Test invalid characters (currently ignoring trailing junk, but see QTBUG-80038).
1193 QTest::newRow(dataTag: "RFC 850 and 1036 invalid character at end")
1194 << QString::fromLatin1(str: "Sun Jan 01 08:00:00 2012 +0100!")
1195 << Qt::RFC2822Date << QDate(2012, 1, 1);
1196 QTest::newRow(dataTag: "RFC 850 and 1036 invalid character at front")
1197 << QString::fromLatin1(str: "!Sun Jan 01 08:00:00 2012 +0100")
1198 << Qt::RFC2822Date << QDate();
1199 QTest::newRow(dataTag: "RFC 850 and 1036 invalid character both ends")
1200 << QString::fromLatin1(str: "!Sun Jan 01 08:00:00 2012 +0100!")
1201 << Qt::RFC2822Date << QDate();
1202 QTest::newRow(dataTag: "RFC 850 and 1036 invalid character at front, 2 at back")
1203 << QString::fromLatin1(str: "!Sun Jan 01 08:00:00 2012 +0100..")
1204 << Qt::RFC2822Date << QDate();
1205 QTest::newRow(dataTag: "RFC 850 and 1036 invalid character 2 at front")
1206 << QString::fromLatin1(str: "!!Sun Jan 01 08:00:00 2012 +0100")
1207 << Qt::RFC2822Date << QDate();
1208 // Again, check the text in the "invalid character" tests isn't the source of invalidity:
1209 QTest::newRow(dataTag: "RFC 850 and 1036 (not invalid)")
1210 << QString::fromLatin1(str: "Sun Jan 01 08:00:00 2012 +0100")
1211 << Qt::RFC2822Date << QDate(2012, 1, 1);
1212
1213 QTest::newRow(dataTag: "RFC empty") << QString::fromLatin1(str: "") << Qt::RFC2822Date << QDate();
1214}
1215
1216void tst_QDate::fromStringDateFormat()
1217{
1218 QFETCH(QString, dateStr);
1219 QFETCH(Qt::DateFormat, dateFormat);
1220 QFETCH(QDate, expectedDate);
1221
1222 QCOMPARE(QDate::fromString(dateStr, dateFormat), expectedDate);
1223}
1224
1225void tst_QDate::fromStringFormat_data()
1226{
1227 QTest::addColumn<QString>(name: "string");
1228 QTest::addColumn<QString>(name: "format");
1229 QTest::addColumn<QDate>(name: "expected");
1230
1231 // Undo this (inline the C-locale versions) for ### Qt 6
1232 // Get localized names:
1233 QString january = QLocale::system().monthName(1, format: QLocale::LongFormat);
1234 QString february = QLocale::system().monthName(2, format: QLocale::LongFormat);
1235 QString march = QLocale::system().monthName(3, format: QLocale::LongFormat);
1236 QString august = QLocale::system().monthName(8, format: QLocale::LongFormat);
1237 QString mon = QLocale::system().dayName(1, format: QLocale::ShortFormat);
1238 QString monday = QLocale::system().dayName(1, format: QLocale::LongFormat);
1239 QString tuesday = QLocale::system().dayName(2, format: QLocale::LongFormat);
1240 QString wednesday = QLocale::system().dayName(3, format: QLocale::LongFormat);
1241 QString thursday = QLocale::system().dayName(4, format: QLocale::LongFormat);
1242 QString friday = QLocale::system().dayName(5, format: QLocale::LongFormat);
1243 QString saturday = QLocale::system().dayName(6, format: QLocale::LongFormat);
1244 QString sunday = QLocale::system().dayName(7, format: QLocale::LongFormat);
1245
1246 QTest::newRow(dataTag: "data0") << QString("") << QString("") << defDate();
1247 QTest::newRow(dataTag: "data1") << QString(" ") << QString("") << invalidDate();
1248 QTest::newRow(dataTag: "data2") << QString(" ") << QString(" ") << defDate();
1249 QTest::newRow(dataTag: "data3") << QString("-%$%#") << QString("$*(#@") << invalidDate();
1250 QTest::newRow(dataTag: "data4") << QString("d") << QString("'d'") << defDate();
1251 QTest::newRow(dataTag: "data5") << QString("101010") << QString("dMyy") << QDate(1910, 10, 10);
1252 QTest::newRow(dataTag: "data6") << QString("101010b") << QString("dMyy") << invalidDate();
1253 QTest::newRow(dataTag: "data7") << january << QString("MMMM") << defDate();
1254 QTest::newRow(dataTag: "data8") << QString("ball") << QString("balle") << invalidDate();
1255 QTest::newRow(dataTag: "data9") << QString("balleh") << QString("balleh") << defDate();
1256 QTest::newRow(dataTag: "data10") << QString("10.01.1") << QString("M.dd.d") << QDate(defDate().year(), 10, 1);
1257 QTest::newRow(dataTag: "data11") << QString("-1.01.1") << QString("M.dd.d") << invalidDate();
1258 QTest::newRow(dataTag: "data12") << QString("11010") << QString("dMMyy") << invalidDate();
1259 QTest::newRow(dataTag: "data13") << QString("-2") << QString("d") << invalidDate();
1260 QTest::newRow(dataTag: "data14") << QString("132") << QString("Md") << invalidDate();
1261 QTest::newRow(dataTag: "data15") << february << QString("MMMM") << QDate(defDate().year(), 2, 1);
1262
1263 QString date = mon + QLatin1Char(' ') + august + " 8 2005";
1264 QTest::newRow(dataTag: "data16") << date << QString("ddd MMMM d yyyy") << QDate(2005, 8, 8);
1265 QTest::newRow(dataTag: "data17") << QString("2000:00") << QString("yyyy:yy") << QDate(2000, 1, 1);
1266 QTest::newRow(dataTag: "data18") << QString("1999:99") << QString("yyyy:yy") << QDate(1999, 1, 1);
1267 QTest::newRow(dataTag: "data19") << QString("2099:99") << QString("yyyy:yy") << QDate(2099, 1, 1);
1268 QTest::newRow(dataTag: "data20") << QString("2001:01") << QString("yyyy:yy") << QDate(2001, 1, 1);
1269 QTest::newRow(dataTag: "data21") << QString("99") << QString("yy") << QDate(1999, 1, 1);
1270 QTest::newRow(dataTag: "data22") << QString("01") << QString("yy") << QDate(1901, 1, 1);
1271
1272 QTest::newRow(dataTag: "data23") << monday << QString("dddd") << QDate(1900, 1, 1);
1273 QTest::newRow(dataTag: "data24") << tuesday << QString("dddd") << QDate(1900, 1, 2);
1274 QTest::newRow(dataTag: "data25") << wednesday << QString("dddd") << QDate(1900, 1, 3);
1275 QTest::newRow(dataTag: "data26") << thursday << QString("dddd") << QDate(1900, 1, 4);
1276 QTest::newRow(dataTag: "data27") << friday << QString("dddd") << QDate(1900, 1, 5);
1277 QTest::newRow(dataTag: "data28") << saturday << QString("dddd") << QDate(1900, 1, 6);
1278 QTest::newRow(dataTag: "data29") << sunday << QString("dddd") << QDate(1900, 1, 7);
1279
1280 QTest::newRow(dataTag: "data30") << monday + " 2006" << QString("dddd yyyy") << QDate(2006, 1, 2);
1281 QTest::newRow(dataTag: "data31") << tuesday + " 2006" << QString("dddd yyyy") << QDate(2006, 1, 3);
1282 QTest::newRow(dataTag: "data32") << wednesday + " 2006" << QString("dddd yyyy") << QDate(2006, 1, 4);
1283 QTest::newRow(dataTag: "data33") << thursday + " 2006" << QString("dddd yyyy") << QDate(2006, 1, 5);
1284 QTest::newRow(dataTag: "data34") << friday + " 2006" << QString("dddd yyyy") << QDate(2006, 1, 6);
1285 QTest::newRow(dataTag: "data35") << saturday + " 2006" << QString("dddd yyyy") << QDate(2006, 1, 7);
1286 QTest::newRow(dataTag: "data36") << sunday + " 2006" << QString("dddd yyyy") << QDate(2006, 1, 1);
1287
1288 QTest::newRow(dataTag: "data37") << tuesday + " 2007 " + march << QString("dddd yyyy MMMM") << QDate(2007, 3, 6);
1289
1290 QTest::newRow(dataTag: "data38") << QString("21052006") << QString("ddMMyyyy") << QDate(2006,5,21);
1291 QTest::newRow(dataTag: "data39") << QString("210506") << QString("ddMMyy") << QDate(1906,5,21);
1292 QTest::newRow(dataTag: "data40") << QString("21/5/2006") << QString("d/M/yyyy") << QDate(2006,5,21);
1293 QTest::newRow(dataTag: "data41") << QString("21/5/06") << QString("d/M/yy") << QDate(1906,5,21);
1294 QTest::newRow(dataTag: "data42") << QString("20060521") << QString("yyyyMMdd") << QDate(2006,5,21);
1295 QTest::newRow(dataTag: "data43") << QString("060521") << QString("yyMMdd") << QDate(1906,5,21);
1296 QTest::newRow(dataTag: "lateMarch") << QString("9999-03-06") << QString("yyyy-MM-dd") << QDate(9999, 3, 6);
1297 QTest::newRow(dataTag: "late") << QString("9999-12-31") << QString("yyyy-MM-dd") << QDate(9999, 12, 31);
1298}
1299
1300
1301void tst_QDate::fromStringFormat()
1302{
1303 QFETCH(QString, string);
1304 QFETCH(QString, format);
1305 QFETCH(QDate, expected);
1306
1307 QDate dt = QDate::fromString(s: string, format);
1308 QCOMPARE(dt, expected);
1309}
1310
1311void tst_QDate::toStringFormat_data()
1312{
1313 QTest::addColumn<QDate>(name: "t");
1314 QTest::addColumn<QString>(name: "format");
1315 QTest::addColumn<QString>(name: "str");
1316
1317 QTest::newRow( dataTag: "data0" ) << QDate(1995,5,20) << QString("d-M-yy") << QString("20-5-95");
1318 QTest::newRow( dataTag: "data1" ) << QDate(2002,12,17) << QString("dd-MM-yyyy") << QString("17-12-2002");
1319 QTest::newRow( dataTag: "data2" ) << QDate(1995,5,20) << QString("M-yy") << QString("5-95");
1320 QTest::newRow( dataTag: "data3" ) << QDate(2002,12,17) << QString("dd") << QString("17");
1321 QTest::newRow( dataTag: "data4" ) << QDate() << QString("dd-mm-yyyy") << QString();
1322}
1323
1324void tst_QDate::toStringFormat()
1325{
1326 QFETCH( QDate, t );
1327 QFETCH( QString, format );
1328 QFETCH( QString, str );
1329
1330 QCOMPARE( t.toString( format ), str );
1331}
1332
1333void tst_QDate::toStringDateFormat_data()
1334{
1335 QTest::addColumn<QDate>(name: "date");
1336 QTest::addColumn<Qt::DateFormat>(name: "format");
1337 QTest::addColumn<QString>(name: "expectedStr");
1338
1339 QTest::newRow(dataTag: "data0") << QDate(1,1,1) << Qt::ISODate << QString("0001-01-01");
1340 QTest::newRow(dataTag: "data1") << QDate(11,1,1) << Qt::ISODate << QString("0011-01-01");
1341 QTest::newRow(dataTag: "data2") << QDate(111,1,1) << Qt::ISODate << QString("0111-01-01");
1342 QTest::newRow(dataTag: "data3") << QDate(1974,12,1) << Qt::ISODate << QString("1974-12-01");
1343 QTest::newRow(dataTag: "year < 0") << QDate(-1,1,1) << Qt::ISODate << QString();
1344 QTest::newRow(dataTag: "year > 9999") << QDate(-1,1,1) << Qt::ISODate << QString();
1345 QTest::newRow(dataTag: "RFC2822Date") << QDate(1974,12,1) << Qt::RFC2822Date << QString("01 Dec 1974");
1346 QTest::newRow(dataTag: "ISODateWithMs") << QDate(1974,12,1) << Qt::ISODateWithMs << QString("1974-12-01");
1347}
1348
1349void tst_QDate::toStringDateFormat()
1350{
1351 QFETCH(QDate, date);
1352 QFETCH(Qt::DateFormat, format);
1353 QFETCH(QString, expectedStr);
1354
1355#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1356 QCOMPARE(date.toString(Qt::SystemLocaleShortDate), QLocale::system().toString(date, QLocale::ShortFormat));
1357 QCOMPARE(date.toString(Qt::DefaultLocaleShortDate), QLocale().toString(date, QLocale::ShortFormat));
1358 QCOMPARE(date.toString(Qt::SystemLocaleLongDate), QLocale::system().toString(date, QLocale::LongFormat));
1359 QCOMPARE(date.toString(Qt::DefaultLocaleLongDate), QLocale().toString(date, QLocale::LongFormat));
1360 QLocale::setDefault(QLocale::German);
1361 QCOMPARE(date.toString(Qt::SystemLocaleShortDate), QLocale::system().toString(date, QLocale::ShortFormat));
1362 QCOMPARE(date.toString(Qt::DefaultLocaleShortDate), QLocale().toString(date, QLocale::ShortFormat));
1363 QCOMPARE(date.toString(Qt::SystemLocaleLongDate), QLocale::system().toString(date, QLocale::LongFormat));
1364 QCOMPARE(date.toString(Qt::DefaultLocaleLongDate), QLocale().toString(date, QLocale::LongFormat));
1365#endif // ### Qt 6: remove
1366
1367 QCOMPARE(date.toString(format), expectedStr);
1368}
1369
1370void tst_QDate::isLeapYear()
1371{
1372 QVERIFY(QDate::isLeapYear(-4801));
1373 QVERIFY(!QDate::isLeapYear(-4800));
1374 QVERIFY(QDate::isLeapYear(-4445));
1375 QVERIFY(!QDate::isLeapYear(-4444));
1376 QVERIFY(!QDate::isLeapYear(-6));
1377 QVERIFY(QDate::isLeapYear(-5));
1378 QVERIFY(!QDate::isLeapYear(-4));
1379 QVERIFY(!QDate::isLeapYear(-3));
1380 QVERIFY(!QDate::isLeapYear(-2));
1381 QVERIFY(QDate::isLeapYear(-1));
1382 QVERIFY(!QDate::isLeapYear(0)); // Doesn't exist
1383 QVERIFY(!QDate::isLeapYear(1));
1384 QVERIFY(!QDate::isLeapYear(2));
1385 QVERIFY(!QDate::isLeapYear(3));
1386 QVERIFY(QDate::isLeapYear(4));
1387 QVERIFY(!QDate::isLeapYear(7));
1388 QVERIFY(QDate::isLeapYear(8));
1389 QVERIFY(!QDate::isLeapYear(100));
1390 QVERIFY(QDate::isLeapYear(400));
1391 QVERIFY(!QDate::isLeapYear(700));
1392 QVERIFY(!QDate::isLeapYear(1500));
1393 QVERIFY(QDate::isLeapYear(1600));
1394 QVERIFY(!QDate::isLeapYear(1700));
1395 QVERIFY(!QDate::isLeapYear(1800));
1396 QVERIFY(!QDate::isLeapYear(1900));
1397 QVERIFY(QDate::isLeapYear(2000));
1398 QVERIFY(!QDate::isLeapYear(2100));
1399 QVERIFY(!QDate::isLeapYear(2200));
1400 QVERIFY(!QDate::isLeapYear(2300));
1401 QVERIFY(QDate::isLeapYear(2400));
1402 QVERIFY(!QDate::isLeapYear(2500));
1403 QVERIFY(!QDate::isLeapYear(2600));
1404 QVERIFY(!QDate::isLeapYear(2700));
1405 QVERIFY(QDate::isLeapYear(2800));
1406
1407 for (int i = -4713; i <= 10000; ++i) {
1408 if (i == 0)
1409 continue;
1410 QVERIFY(!QDate(i, 2, 29).isValid() == !QDate::isLeapYear(i));
1411 }
1412}
1413
1414void tst_QDate::yearsZeroToNinetyNine()
1415{
1416 {
1417 QDate dt(-1, 2, 3);
1418 QCOMPARE(dt.year(), -1);
1419 QCOMPARE(dt.month(), 2);
1420 QCOMPARE(dt.day(), 3);
1421 }
1422
1423 {
1424 QDate dt(1, 2, 3);
1425 QCOMPARE(dt.year(), 1);
1426 QCOMPARE(dt.month(), 2);
1427 QCOMPARE(dt.day(), 3);
1428 }
1429
1430 {
1431 QDate dt(99, 2, 3);
1432 QCOMPARE(dt.year(), 99);
1433 QCOMPARE(dt.month(), 2);
1434 QCOMPARE(dt.day(), 3);
1435 }
1436
1437 QVERIFY(!QDate::isValid(0, 2, 3));
1438 QVERIFY(QDate::isValid(1, 2, 3));
1439 QVERIFY(QDate::isValid(-1, 2, 3));
1440
1441#if QT_DEPRECATED_SINCE(5,0)
1442 {
1443 QDate dt;
1444 dt.setYMD(1, 2, 3);
1445 QCOMPARE(dt.year(), 1901);
1446 QCOMPARE(dt.month(), 2);
1447 QCOMPARE(dt.day(), 3);
1448 }
1449#endif
1450
1451 {
1452 QDate dt;
1453 dt.setDate(year: 1, month: 2, day: 3);
1454 QCOMPARE(dt.year(), 1);
1455 QCOMPARE(dt.month(), 2);
1456 QCOMPARE(dt.day(), 3);
1457
1458 dt.setDate(year: 0, month: 2, day: 3);
1459 QVERIFY(!dt.isValid());
1460 }
1461}
1462
1463void tst_QDate::printNegativeYear_data() const
1464{
1465 QTest::addColumn<int>(name: "year");
1466 QTest::addColumn<QString>(name: "expect");
1467 QTest::newRow(dataTag: "millennium") << -1000 << QStringLiteral("-1000");
1468 QTest::newRow(dataTag: "century") << -500 << QStringLiteral("-0500");
1469 QTest::newRow(dataTag: "decade") << -20 << QStringLiteral("-0020");
1470 QTest::newRow(dataTag: "year") << -7 << QStringLiteral("-0007");
1471}
1472
1473void tst_QDate::printNegativeYear() const
1474{
1475 QFETCH(int, year);
1476 QFETCH(QString, expect);
1477#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
1478 expect.replace(QLatin1Char('-'), QLocale().negativeSign());
1479#endif
1480
1481 QDate date(year, 3, 4);
1482 QVERIFY(date.isValid());
1483 QCOMPARE(date.year(), year);
1484 QCOMPARE(date.toString(QLatin1String("yyyy")), expect);
1485}
1486
1487#if QT_CONFIG(textdate) && QT_DEPRECATED_SINCE(5, 10)
1488QT_WARNING_PUSH // the methods tested here are all deprecated
1489QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations")
1490
1491void tst_QDate::shortDayName() const
1492{
1493 QCOMPARE(QDate::shortDayName(0), QString());
1494 QCOMPARE(QDate::shortDayName(8), QString());
1495
1496 if (QLocale::system().language() == QLocale::C) {
1497 QCOMPARE(QDate::shortDayName(1), QLatin1String("Mon"));
1498 QCOMPARE(QDate::shortDayName(7), QLatin1String("Sun"));
1499 }
1500
1501 QLocale locale = QLocale::system();
1502 for(int i = 1; i <= 7; ++i) {
1503 QCOMPARE(QDate::shortDayName(i), locale.dayName(i, QLocale::ShortFormat));
1504 }
1505}
1506
1507void tst_QDate::standaloneShortDayName() const
1508{
1509 QCOMPARE(QDate::shortDayName(0, QDate::StandaloneFormat), QString());
1510 QCOMPARE(QDate::shortDayName(8, QDate::StandaloneFormat), QString());
1511
1512 if (QLocale::system().language() == QLocale::C) {
1513 QCOMPARE(QDate::shortDayName(1, QDate::StandaloneFormat), QLatin1String("Mon"));
1514 QCOMPARE(QDate::shortDayName(7, QDate::StandaloneFormat), QLatin1String("Sun"));
1515 }
1516
1517 QLocale locale = QLocale::system();
1518 for(int i = 1; i <= 7; ++i) {
1519 QCOMPARE(QDate::shortDayName(i, QDate::StandaloneFormat), locale.standaloneDayName(i, QLocale::ShortFormat));
1520 }
1521}
1522
1523void tst_QDate::longDayName() const
1524{
1525 QCOMPARE(QDate::longDayName(0), QString());
1526 QCOMPARE(QDate::longDayName(8), QString());
1527
1528 if (QLocale::system().language() == QLocale::C) {
1529 QCOMPARE(QDate::longDayName(1), QLatin1String("Monday"));
1530 QCOMPARE(QDate::longDayName(7), QLatin1String("Sunday"));
1531 }
1532
1533 QLocale locale = QLocale::system();
1534 for(int i = 1; i <= 7; ++i) {
1535 QCOMPARE(QDate::longDayName(i), locale.dayName(i, QLocale::LongFormat));
1536 }
1537}
1538
1539void tst_QDate::standaloneLongDayName() const
1540{
1541 QCOMPARE(QDate::longDayName(0, QDate::StandaloneFormat), QString());
1542 QCOMPARE(QDate::longDayName(8, QDate::StandaloneFormat), QString());
1543
1544 if (QLocale::system().language() == QLocale::C) {
1545 QCOMPARE(QDate::longDayName(1, QDate::StandaloneFormat), QLatin1String("Monday"));
1546 QCOMPARE(QDate::longDayName(7, QDate::StandaloneFormat), QLatin1String("Sunday"));
1547 }
1548
1549 QLocale locale = QLocale::system();
1550 for(int i = 1; i <= 7; ++i) {
1551 QCOMPARE(QDate::longDayName(i, QDate::StandaloneFormat), locale.standaloneDayName(i, QLocale::LongFormat));
1552 }
1553}
1554
1555void tst_QDate::shortMonthName() const
1556{
1557 QCOMPARE(QDate::shortMonthName(0), QString());
1558 QCOMPARE(QDate::shortMonthName(13), QString());
1559
1560 if (QLocale::system().language() == QLocale::C) {
1561 QCOMPARE(QDate::shortMonthName(1), QLatin1String("Jan"));
1562 QCOMPARE(QDate::shortMonthName(8), QLatin1String("Aug"));
1563 }
1564
1565 QLocale locale = QLocale::system();
1566 for(int i = 1; i <= 12; ++i) {
1567 QCOMPARE(QDate::shortMonthName(i), locale.monthName(i, QLocale::ShortFormat));
1568 }
1569}
1570
1571void tst_QDate::standaloneShortMonthName() const
1572{
1573 QCOMPARE(QDate::shortMonthName(0, QDate::StandaloneFormat), QString());
1574 QCOMPARE(QDate::shortMonthName(13, QDate::StandaloneFormat), QString());
1575
1576 if (QLocale::system().language() == QLocale::C) {
1577 QCOMPARE(QDate::shortMonthName(1, QDate::StandaloneFormat), QLatin1String("Jan"));
1578 QCOMPARE(QDate::shortMonthName(8, QDate::StandaloneFormat), QLatin1String("Aug"));
1579 }
1580
1581 QLocale locale = QLocale::system();
1582 for(int i = 1; i <= 12; ++i) {
1583 QCOMPARE(QDate::shortMonthName(i, QDate::StandaloneFormat), locale.standaloneMonthName(i, QLocale::ShortFormat));
1584 }
1585}
1586
1587void tst_QDate::longMonthName() const
1588{
1589 QCOMPARE(QDate::longMonthName(0), QString());
1590 QCOMPARE(QDate::longMonthName(13), QString());
1591
1592 if (QLocale::system().language() == QLocale::C) {
1593 QCOMPARE(QDate::longMonthName(1), QLatin1String("January"));
1594 QCOMPARE(QDate::longMonthName(8), QLatin1String("August"));
1595 }
1596
1597 QLocale locale = QLocale::system();
1598 for(int i = 1; i <= 12; ++i) {
1599 QCOMPARE(QDate::longMonthName(i), locale.monthName(i, QLocale::LongFormat));
1600 }
1601}
1602
1603void tst_QDate::standaloneLongMonthName() const
1604{
1605 QCOMPARE(QDate::longMonthName(0, QDate::StandaloneFormat), QString());
1606 QCOMPARE(QDate::longMonthName(13, QDate::StandaloneFormat), QString());
1607
1608 if (QLocale::system().language() == QLocale::C) {
1609 QCOMPARE(QDate::longMonthName(1, QDate::StandaloneFormat), QLatin1String("January"));
1610 QCOMPARE(QDate::longMonthName(8, QDate::StandaloneFormat), QLatin1String("August"));
1611 }
1612
1613 QLocale locale = QLocale::system();
1614 for(int i = 1; i <= 12; ++i) {
1615 QCOMPARE(QDate::longMonthName(i, QDate::StandaloneFormat), locale.standaloneMonthName(i, QLocale::LongFormat));
1616 }
1617}
1618QT_WARNING_POP
1619
1620void tst_QDate::roundtripString() const
1621{
1622 /* This code path should not result in warnings, no matter what locale is set. */
1623 const QDate date(QDate::currentDate());
1624 QCOMPARE(date.fromString(date.toString(Qt::TextDate), Qt::TextDate), date);
1625
1626 const QDateTime now(QDateTime::currentDateTime());
1627 const QDateTime when = now.addMSecs(msecs: -now.time().msec()); // TextDate rounds to whole seconds.
1628 QCOMPARE(when.fromString(when.toString(Qt::TextDate), Qt::TextDate), when);
1629}
1630#endif // textdate
1631
1632void tst_QDate::roundtrip() const
1633{
1634 // Test round trip, this exercises setDate(), isValid(), isLeapYear(),
1635 // year(), month(), day(), julianDayFromDate(), and getDateFromJulianDay()
1636 // to ensure they are internally consistent (but doesn't guarantee correct)
1637
1638 // Test Julian round trip around JD 0 and the c++ integer division rounding
1639 // problem point (eg. negative numbers) in the conversion functions.
1640 QDate testDate;
1641 QDate loopDate = QDate::fromJulianDay(jd_: -50001); // 1 Jan 4850 BC
1642 while (loopDate.toJulianDay() <= 5150) { // 31 Dec 4700 BC
1643 testDate.setDate(year: loopDate.year(), month: loopDate.month(), day: loopDate.day());
1644 QCOMPARE(loopDate.toJulianDay(), testDate.toJulianDay());
1645 loopDate = loopDate.addDays(days: 1);
1646 }
1647
1648 // Test Julian round trip in both BC and AD
1649 loopDate = QDate::fromJulianDay(jd_: 1684901); // 1 Jan 100 BC
1650 while (loopDate.toJulianDay() <= 1757949) { // 31 Dec 100 AD
1651 testDate.setDate(year: loopDate.year(), month: loopDate.month(), day: loopDate.day());
1652 QCOMPARE(loopDate.toJulianDay(), testDate.toJulianDay());
1653 loopDate = loopDate.addDays(days: 1);
1654 }
1655
1656 // Test Gregorian round trip during current useful period
1657 loopDate = QDate::fromJulianDay(jd_: 2378497); // 1 Jan 1900 AD
1658 while (loopDate.toJulianDay() <= 2488433) { // 31 Dec 2100 AD
1659 testDate.setDate(year: loopDate.year(), month: loopDate.month(), day: loopDate.day());
1660 QCOMPARE(loopDate.toJulianDay(), testDate.toJulianDay());
1661 loopDate = loopDate.addDays(days: 1);
1662 }
1663
1664 // Test Gregorian round trip at top end of widget/format range
1665 loopDate = QDate::fromJulianDay(jd_: 5336961); // 1 Jan 9900 AD
1666 while (loopDate.toJulianDay() <= 5373484) { // 31 Dec 9999 AD
1667 testDate.setDate(year: loopDate.year(), month: loopDate.month(), day: loopDate.day());
1668 QCOMPARE(loopDate.toJulianDay(), testDate.toJulianDay());
1669 loopDate = loopDate.addDays(days: 1);
1670 }
1671
1672 qint64 minJd = Q_INT64_C(-784350574879);
1673 qint64 maxJd = Q_INT64_C( 784354017364);
1674
1675 // Test Gregorian round trip at top end of conversion range
1676 loopDate = QDate::fromJulianDay(jd_: maxJd);
1677 while (loopDate.toJulianDay() >= maxJd - 146397) {
1678 testDate.setDate(year: loopDate.year(), month: loopDate.month(), day: loopDate.day());
1679 QCOMPARE(loopDate.toJulianDay(), testDate.toJulianDay());
1680 loopDate = loopDate.addDays(days: -1);
1681 }
1682
1683 // Test Gregorian round trip at low end of conversion range
1684 loopDate = QDate::fromJulianDay(jd_: minJd);
1685 while (loopDate.toJulianDay() <= minJd + 146397) {
1686 testDate.setDate(year: loopDate.year(), month: loopDate.month(), day: loopDate.day());
1687 QCOMPARE(loopDate.toJulianDay(), testDate.toJulianDay());
1688 loopDate = loopDate.addDays(days: 1);
1689 }
1690}
1691
1692void tst_QDate::qdebug() const
1693{
1694 QTest::ignoreMessage(type: QtDebugMsg, message: "QDate(Invalid)");
1695 qDebug() << QDate();
1696 QTest::ignoreMessage(type: QtDebugMsg, message: "QDate(\"1983-08-07\")");
1697 qDebug() << QDate(1983, 8, 7);
1698}
1699
1700QTEST_APPLESS_MAIN(tst_QDate)
1701#include "tst_qdate.moc"
1702

source code of qtbase/tests/auto/corelib/time/qdate/tst_qdate.cpp