14#include "private/qcalendarmath_p.h"
15#include "private/qdatetime_p.h"
16#if QT_CONFIG(datetimeparser)
17#include "private/qdatetimeparser_p.h"
20#include "private/qcore_mac_p.h"
22#include "private/qgregoriancalendar_p.h"
23#include "private/qlocale_tools_p.h"
24#include "private/qlocaltime_p.h"
25#include "private/qnumeric_p.h"
26#include "private/qstringconverter_p.h"
27#include "private/qstringiterator_p.h"
28#if QT_CONFIG(timezone)
29#include "private/qtimezoneprivate_p.h"
34# include <qt_windows.h>
37#include <private/qtools_p.h>
41using namespace Qt::StringLiterals;
42using namespace QtPrivate::DateTimeConstants;
43using namespace QtMiscUtils;
46
47
50
51
52static_assert(std::is_trivially_copyable_v<QCalendar::YearMonthDay>);
54static inline QDate
fixedDate(QCalendar::YearMonthDay parts, QCalendar cal)
56 if ((parts.year < 0 && !cal.isProleptic()) || (parts.year == 0 && !cal.hasYearZero()))
59 parts.day = qMin(parts.day, cal.daysInMonth(parts.month, parts.year));
60 return cal.dateFromParts(parts);
63static inline QDate
fixedDate(QCalendar::YearMonthDay parts)
66 parts.day = qMin(parts.day, QGregorianCalendar::monthLength(parts.month, parts.year));
67 const auto jd = QGregorianCalendar::julianFromParts(parts.year, parts.month, parts.day);
69 return QDate::fromJulianDay(*jd);
75
76
78#if QT_CONFIG(textdate)
79static const char qt_shortMonthNames[][4] = {
80 "Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
81 "Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
84static int fromShortMonthName(QStringView monthName)
86 for (
unsigned int i = 0; i <
sizeof(qt_shortMonthNames) /
sizeof(qt_shortMonthNames[0]); ++i) {
87 if (monthName == QLatin1StringView(qt_shortMonthNames[i], 3))
94#if QT_CONFIG(datestring)
96using ParsedInt = QSimpleParsedNumber<qulonglong>;
99
100
101ParsedInt readInt(QLatin1StringView text)
107 if (text.isEmpty() || !isAsciiDigit(text.front().toLatin1()))
110 QSimpleParsedNumber res = qstrntoull(text.data(), text.size(), 10);
111 return res.used == text.size() ? res : ParsedInt{};
114ParsedInt readInt(QStringView text)
124 QVarLengthArray<
char> latin1(text.size());
125 QLatin1::convertFromUnicode(latin1.data(), text);
126 return readInt(QLatin1StringView{latin1.data(), latin1.size()});
131struct ParsedRfcDateTime {
137static int shortDayFromName(QStringView name)
139 const char16_t shortDayNames[] = u"MonTueWedThuFriSatSun";
140 for (
int i = 0; i < 7; i++) {
141 if (name == QStringView(shortDayNames + 3 * i, 3))
147static ParsedRfcDateTime rfcDateImpl(QStringView s)
151 ParsedRfcDateTime result;
153 QVarLengthArray<QStringView, 6> words;
155 auto tokens = s.tokenize(u' ', Qt::SkipEmptyParts);
156 auto it = tokens.begin();
157 for (
int i = 0; i < 6 && it != tokens.end(); ++i, ++it)
158 words.emplace_back(*it);
160 if (words.size() < 3 || it != tokens.end())
162 const QChar colon(u':');
166 const auto isShortName = [](QStringView name) {
167 return (name.size() == 3 && name[0].isUpper()
168 && name[1].isLower() && name[2].isLower());
172
173
178 const QStringView maybeDayName = words.front();
179 if (maybeDayName.endsWith(u',')) {
180 dayName = maybeDayName.chopped(1);
181 words.erase(words.begin());
182 }
else if (!maybeDayName.front().isDigit()) {
183 dayName = maybeDayName;
184 words.erase(words.begin());
187 if (words.size() < 3 || words.size() > 5)
191 int dayIndex, monthIndex;
201 yearIndex = words.size() > 3 && words.at(2).contains(colon) ? 3 : 2;
203 if (words.at(yearIndex).size() != 4)
207 if (!dayName.isEmpty()) {
208 if (!isShortName(dayName))
210 dayOfWeek = shortDayFromName(dayName);
215 const int day = words.at(dayIndex).toInt(&ok);
218 const int year = words.at(yearIndex).toInt(&ok);
221 const QStringView monthName = words.at(monthIndex);
222 if (!isShortName(monthName))
224 int month = fromShortMonthName(monthName);
228 date = QDate(year, month, day);
229 if (dayOfWeek && date.dayOfWeek() != dayOfWeek)
232 words.remove(yearIndex);
237 if (words.size() && words.at(0).contains(colon)) {
238 const QStringView when = words.front();
239 words.erase(words.begin());
240 if (when.size() < 5 || when[2] != colon
241 || (when.size() == 8 ? when[5] != colon : when.size() > 5)) {
244 const int hour = when.first(2).toInt(&ok);
247 const int minute = when.sliced(3, 2).toInt(&ok);
250 const auto secs = when.size() == 8 ? when.last(2).toInt(&ok) : 0;
253 time = QTime(hour, minute, secs);
259 const QStringView zone = words.front();
260 words.erase(words.begin());
261 if (words.size() || !(zone.size() == 3 || zone.size() == 5))
266 else if (zone[0] != u'+')
268 const int hour = zone.sliced(1, 2).toInt(&ok);
271 const auto minute = zone.size() == 5 ? zone.last(2).toInt(&ok) : 0;
274 offset = (hour * 60 + minute) * 60;
281 result.utcOffset = offset;
289 return QString::asprintf(
"%c%02d%s%02d",
290 offset >= 0 ?
'+' :
'-',
291 qAbs(offset) /
int(SECS_PER_HOUR),
293 format == Qt::TextDate ?
"" :
":",
294 (qAbs(offset) / 60) % 60);
297#if QT_CONFIG(datestring)
299static int fromOffsetString(QStringView offsetString,
bool *valid)
noexcept
303 const qsizetype size = offsetString.size();
304 if (size < 2 || size > 6)
311 const QChar signChar = offsetString[0];
312 if (signChar == u'+')
314 else if (signChar == u'-')
320 const QStringView time = offsetString.sliced(1);
321 qsizetype hhLen = time.indexOf(u':');
328 const QStringView hhRef = time.first(qMin(hhLen, time.size()));
330 const int hour = hhRef.toInt(&ok);
331 if (!ok || hour > 23)
334 const QStringView mmRef = time.sliced(qMin(mmIndex, time.size()));
335 const int minute = mmRef.isEmpty() ? 0 : mmRef.toInt(&ok);
336 if (!ok || minute < 0 || minute > 59)
340 return sign * ((hour * 60) + minute) * 60;
345
346
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
430
431
432
433
434
435
438
439
440
441
442
443
444
445
446
448QDate::QDate(
int y,
int m,
int d)
450 static_assert(maxJd() == JulianDayMax);
451 static_assert(minJd() == JulianDayMin);
452 jd = QGregorianCalendar::julianFromParts(y, m, d).value_or(nullJd());
455QDate::QDate(
int y,
int m,
int d, QCalendar cal)
457 *
this = cal.dateFromParts(y, m, d);
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
485
486
487
488
489
490
491
492
493
494
497
498
499
500
501
502
503
504
505
506
509
510
511
512
513
514
515
516
517
520
521
522
523
524
525
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
549int QDate::year(QCalendar cal)
const
552 const auto parts = cal.partsFromDate(*
this);
560
561
563int QDate::year()
const
566 const auto parts = QGregorianCalendar::partsFromJulian(jd);
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
601int QDate::month(QCalendar cal)
const
604 const auto parts = cal.partsFromDate(*
this);
612
613
615int QDate::month()
const
618 const auto parts = QGregorianCalendar::partsFromJulian(jd);
626
627
628
629
630
631
632
634int QDate::day(QCalendar cal)
const
637 const auto parts = cal.partsFromDate(*
this);
645
646
648int QDate::day()
const
651 const auto parts = QGregorianCalendar::partsFromJulian(jd);
659
660
661
662
663
664
665
666
668int QDate::dayOfWeek(QCalendar cal)
const
673 return cal.dayOfWeek(*
this);
677
678
680int QDate::dayOfWeek()
const
682 return isValid() ? QGregorianCalendar::weekDayOfJulian(jd) : 0;
686
687
688
689
690
691
692
694int QDate::dayOfYear(QCalendar cal)
const
697 QDate firstDay = cal.dateFromParts(year(cal), 1, 1);
698 if (firstDay.isValid())
699 return firstDay.daysTo(*
this) + 1;
705
706
708int QDate::dayOfYear()
const
711 if (
const auto first = QGregorianCalendar::julianFromParts(year(), 1, 1))
712 return jd - *first + 1;
718
719
720
721
722
723
724
725
727int QDate::daysInMonth(QCalendar cal)
const
730 const auto parts = cal.partsFromDate(*
this);
732 return cal.daysInMonth(parts.month, parts.year);
738
739
741int QDate::daysInMonth()
const
744 const auto parts = QGregorianCalendar::partsFromJulian(jd);
746 return QGregorianCalendar::monthLength(parts.month, parts.year);
752
753
754
755
756
757
758
760int QDate::daysInYear(QCalendar cal)
const
765 return cal.daysInYear(year(cal));
769
770
772int QDate::daysInYear()
const
774 return isValid() ? QGregorianCalendar::leapTest(year()) ? 366 : 365 : 0;
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
796int QDate::weekNumber(
int *yearNumber)
const
803 const QDate thursday(addDays(4 - dayOfWeek()));
805 *yearNumber = thursday.year();
808 return (thursday.dayOfYear() + 6) / 7;
811#if QT_DEPRECATED_SINCE(6
, 9
)
813static QTimeZone asTimeZone(Qt::TimeSpec spec,
int offset,
const char *warner)
818 qWarning(
"%s: Pass a QTimeZone instead of Qt::TimeZone.", warner);
822 qWarning(
"%s: Ignoring offset (%d seconds) passed with Qt::LocalTime",
828 qWarning(
"%s: Ignoring offset (%d seconds) passed with Qt::UTC",
833 case Qt::OffsetFromUTC:
837 return QTimeZone::isUtcOrFixedOffset(spec)
838 ? QTimeZone::fromSecondsAheadOfUtc(offset)
839 : QTimeZone(QTimeZone::LocalTime);
847 using Bounds = std::numeric_limits<qint64>;
848 if (jd < Bounds::min() + JULIAN_DAY_FOR_EPOCH)
850 jd -= JULIAN_DAY_FOR_EPOCH;
851 const qint64 maxDay = Bounds::max() / MSECS_PER_DAY;
852 const qint64 minDay = Bounds::min() / MSECS_PER_DAY - 1;
858 return jd > minDay && jd <= maxDay;
860 return jd >= minDay && jd < maxDay;
862 Q_UNREACHABLE_RETURN(
false);
867 Q_ASSERT(!zone.isUtcOrFixedOffset());
869 const auto moment = [=](QTime time) {
870 return QDateTime(day, time, zone, QDateTime::TransitionResolution::Reject);
873 QDateTime when = moment(QTime(2, 0));
874 if (!when.isValid()) {
876 when = moment(QTime(12, 0));
877 if (!when.isValid()) {
879 when = moment(QTime(23, 59, 59, 999));
884 int high = when.time().msecsSinceStartOfDay() / 60000;
887 while (high > low + 1) {
888 const int mid = (high + low) / 2;
889 const QDateTime probe = QDateTime(day, QTime(mid / 60, mid % 60), zone,
890 QDateTime::TransitionResolution::PreferBefore);
891 if (probe.isValid() && probe.date() == day) {
901 if (QDateTime p = moment(when.time().addSecs(-1)); Q_UNLIKELY(p.isValid() && p.date() == day)) {
904 while (high > low + 1) {
905 const int mid = (high + low) / 2;
906 const int min = mid / 60;
907 const QDateTime probe = moment(QTime(min / 60, min % 60, mid % 60));
908 if (probe.isValid() && probe.date() == day) {
916 return when.isValid() ? when : QDateTime();
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947QDateTime QDate::startOfDay(
const QTimeZone &zone)
const
949 if (!inDateTimeRange(jd, DaySide::Start) || !zone.isValid())
952 QDateTime when(*
this, QTime(0, 0), zone,
953 QDateTime::TransitionResolution::RelativeToBefore);
954 if (Q_UNLIKELY(!when.isValid() || when.date() != *
this)) {
955#if QT_CONFIG(timezone)
957 if (zone.timeSpec() == Qt::TimeZone && zone.hasTransitions()) {
958 QTimeZone::OffsetData tran
961 = zone.previousTransition(QDateTime(addDays(1), QTime(12, 0), zone));
962 const QDateTime &at = tran.atUtc.toTimeZone(zone);
963 if (at.isValid() && at.date() == *
this)
968 when = toEarliest(*
this, zone);
975
976
977
978QDateTime QDate::startOfDay()
const
980 return startOfDay(QTimeZone::LocalTime);
983#if QT_DEPRECATED_SINCE(6
, 9
)
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012QDateTime QDate::startOfDay(Qt::TimeSpec spec,
int offsetSeconds)
const
1014 QTimeZone zone = asTimeZone(spec, offsetSeconds,
"QDate::startOfDay");
1016 return zone.timeSpec() == spec ? startOfDay(zone) : QDateTime();
1020static QDateTime
toLatest(QDate day,
const QTimeZone &zone)
1022 Q_ASSERT(!zone.isUtcOrFixedOffset());
1024 const auto moment = [=](QTime time) {
1025 return QDateTime(day, time, zone, QDateTime::TransitionResolution::Reject);
1028 QDateTime when = moment(QTime(21, 59, 59, 999));
1029 if (!when.isValid()) {
1031 when = moment(QTime(12, 0));
1032 if (!when.isValid()) {
1034 when = moment(QTime(0, 0));
1035 if (!when.isValid())
1040 int low = when.time().msecsSinceStartOfDay() / 60000;
1042 while (high > low + 1) {
1043 const int mid = (high + low) / 2;
1044 const QDateTime probe = QDateTime(day, QTime(mid / 60, mid % 60, 59, 999), zone,
1045 QDateTime::TransitionResolution::PreferAfter);
1046 if (probe.isValid() && probe.date() == day) {
1056 if (QDateTime p = moment(when.time().addSecs(1)); Q_UNLIKELY(p.isValid() && p.date() == day)) {
1059 while (high > low + 1) {
1060 const int mid = (high + low) / 2;
1061 const int min = mid / 60;
1062 const QDateTime probe = moment(QTime(min / 60, min % 60, mid % 60, 999));
1063 if (probe.isValid() && probe.date() == day) {
1071 return when.isValid() ? when : QDateTime();
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103QDateTime QDate::endOfDay(
const QTimeZone &zone)
const
1105 if (!inDateTimeRange(jd, DaySide::End) || !zone.isValid())
1108 QDateTime when(*
this, QTime(23, 59, 59, 999), zone,
1109 QDateTime::TransitionResolution::RelativeToAfter);
1110 if (Q_UNLIKELY(!when.isValid() || when.date() != *
this)) {
1111#if QT_CONFIG(timezone)
1113 if (zone.timeSpec() == Qt::TimeZone && zone.hasTransitions()) {
1114 QTimeZone::OffsetData tran
1117 = zone.nextTransition(QDateTime(addDays(-1), QTime(12, 0), zone));
1118 const QDateTime &at = tran.atUtc.toTimeZone(zone);
1119 if (at.isValid() && at.date() == *
this)
1124 when = toLatest(*
this, zone);
1130
1131
1132
1133QDateTime QDate::endOfDay()
const
1135 return endOfDay(QTimeZone::LocalTime);
1138#if QT_DEPRECATED_SINCE(6
, 9
)
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167QDateTime QDate::endOfDay(Qt::TimeSpec spec,
int offsetSeconds)
const
1169 QTimeZone zone = asTimeZone(spec, offsetSeconds,
"QDate::endOfDay");
1171 return endOfDay(zone);
1175#if QT_CONFIG(datestring)
1177static QString toStringTextDate(QDate date)
1179 if (date.isValid()) {
1181 const auto parts = cal.partsFromDate(date);
1182 if (parts.isValid()) {
1183 const QLatin1Char sp(
' ');
1184 return QLocale::c().dayName(cal.dayOfWeek(date), QLocale::ShortFormat) + sp
1185 + cal.monthName(QLocale::c(), parts.month, parts.year, QLocale::ShortFormat)
1187 + sp + QString::asprintf(
"%d %04d", parts.day, parts.year);
1193static QString toStringIsoDate(QDate date)
1195 const auto parts = QCalendar().partsFromDate(date);
1196 if (parts.isValid() && parts.year >= 0 && parts.year <= 9999)
1197 return QString::asprintf(
"%04d-%02d-%02d", parts.year, parts.month, parts.day);
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229QString QDate::toString(Qt::DateFormat format)
const
1235 case Qt::RFC2822Date:
1236 return QLocale::c().toString(*
this, u"dd MMM yyyy");
1239 return toStringTextDate(*
this);
1241 case Qt::ISODateWithMs:
1243 return toStringIsoDate(*
this);
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309QString QDate::toString(QStringView format, QCalendar cal)
const
1311 return QLocale::c().toString(*
this, format, cal);
1316
1317
1318
1319QString QDate::toString(QStringView format)
const
1321 return QLocale::c().toString(*
this, format, QCalendar());
1325
1326
1327
1328QString QDate::toString(
const QString &format)
const
1330 return QLocale::c().toString(*
this, qToStringViewIgnoringNull(format), QCalendar());
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344bool QDate::setDate(
int year,
int month,
int day)
1346 const auto maybe = QGregorianCalendar::julianFromParts(year, month, day);
1347 jd = maybe.value_or(nullJd());
1352
1353
1354
1355
1356
1357
1358
1359
1360
1362bool QDate::setDate(
int year,
int month,
int day, QCalendar cal)
1364 *
this = QDate(year, month, day, cal);
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380void QDate::getDate(
int *year,
int *month,
int *day)
const
1382 QCalendar::YearMonthDay parts;
1384 parts = QGregorianCalendar::partsFromJulian(jd);
1386 const bool ok = parts.isValid();
1388 *year = ok ? parts.year : 0;
1390 *month = ok ? parts.month : 0;
1392 *day = ok ? parts.day : 0;
1396
1397
1398
1399
1400
1401
1402
1403
1405QDate QDate::addDays(qint64 ndays)
const
1410 if (qint64 r; Q_UNLIKELY(qAddOverflow(jd, ndays, &r)))
1413 return fromJulianDay(r);
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1451QDate QDate::addMonths(
int nmonths, QCalendar cal)
const
1459 auto parts = cal.partsFromDate(*
this);
1461 if (!parts.isValid())
1463 Q_ASSERT(parts.year || cal.hasYearZero());
1465 parts.month += nmonths;
1466 while (parts.month <= 0) {
1467 if (--parts.year || cal.hasYearZero())
1468 parts.month += cal.monthsInYear(parts.year);
1470 int count = cal.monthsInYear(parts.year);
1471 while (parts.month > count) {
1472 parts.month -= count;
1473 count = (++parts.year || cal.hasYearZero()) ? cal.monthsInYear(parts.year) : 0;
1476 return fixedDate(parts, cal);
1480
1481
1483QDate QDate::addMonths(
int nmonths)
const
1491 auto parts = QGregorianCalendar::partsFromJulian(jd);
1493 if (!parts.isValid())
1495 Q_ASSERT(parts.year);
1497 parts.month += nmonths;
1498 while (parts.month <= 0) {
1502 while (parts.month > 12) {
1508 return fixedDate(parts);
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1525QDate QDate::addYears(
int nyears, QCalendar cal)
const
1530 auto parts = cal.partsFromDate(*
this);
1531 if (!parts.isValid())
1534 int old_y = parts.year;
1535 parts.year += nyears;
1538 if (!cal.hasYearZero() && ((old_y > 0) != (parts.year > 0) || !parts.year))
1539 parts.year += nyears > 0 ? +1 : -1;
1541 return fixedDate(parts, cal);
1545
1546
1548QDate QDate::addYears(
int nyears)
const
1553 auto parts = QGregorianCalendar::partsFromJulian(jd);
1554 if (!parts.isValid())
1557 int old_y = parts.year;
1558 parts.year += nyears;
1561 if ((old_y > 0) != (parts.year > 0) || !parts.year)
1562 parts.year += nyears > 0 ? +1 : -1;
1564 return fixedDate(parts);
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1579qint64 QDate::daysTo(QDate d)
const
1581 if (isNull() || d.isNull())
1590
1591
1592
1593
1594
1597
1598
1599
1600
1601
1602
1603
1606
1607
1608
1609
1612
1613
1614
1615
1616
1619
1620
1621
1622
1625
1626
1627
1628
1629
1632
1633
1634
1635
1636
1638#if QT_CONFIG(datestring)
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1654
1655
1656
1657QDate QDate::fromString(QStringView string, Qt::DateFormat format)
1659 if (string.isEmpty())
1663 case Qt::RFC2822Date:
1664 return rfcDateImpl(string).date;
1666 case Qt::TextDate: {
1668 QVarLengthArray<QStringView, 4> parts;
1669 auto tokens = string.tokenize(u' ', Qt::SkipEmptyParts);
1670 auto it = tokens.begin();
1671 for (
int i = 0; i < 4 && it != tokens.end(); ++i, ++it)
1672 parts.emplace_back(*it);
1674 if (parts.size() != 4 || it != tokens.end())
1678 int year = parts.at(3).toInt(&ok);
1679 int day = ok ? parts.at(2).toInt(&ok) : 0;
1683 const int month = fromShortMonthName(parts.at(1));
1687 return QDate(year, month, day);
1691 if (string.size() >= 10 && string[4].isPunct() && string[7].isPunct()
1692 && (string.size() == 10 || !string[10].isDigit())) {
1693 const ParsedInt year = readInt(string.first(4));
1694 const ParsedInt month = readInt(string.sliced(5, 2));
1695 const ParsedInt day = readInt(string.sliced(8, 2));
1696 if (year.ok() && year.result > 0 && year.result <= 9999 && month.ok() && day.ok())
1697 return QDate(year.result, month.result, day.result);
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1836
1837
1838
1839
1842
1843
1844
1845QDate QDate::fromString(
const QString &string, QStringView format,
int baseYear, QCalendar cal)
1848#if QT_CONFIG(datetimeparser)
1849 QDateTimeParser dt(QMetaType::QDate, QDateTimeParser::FromString, cal);
1850 dt.setDefaultLocale(QLocale::c());
1851 if (dt.parseFormat(format))
1852 dt.fromString(string, &date,
nullptr, baseYear);
1863
1864
1865
1866
1869
1870
1871
1872
1875
1876
1877
1878
1881
1882
1883
1884
1885
1886
1889
1890
1891
1892
1893
1894QDate QDate::fromString(
const QString &string, QStringView format,
int baseYear)
1896 return fromString(string, format, baseYear, QCalendar());
1900
1901
1902
1903
1904
1905
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1920bool QDate::isValid(
int year,
int month,
int day)
1922 return QGregorianCalendar::validParts(year, month, day);
1926
1927
1928
1929
1930
1931
1932
1934bool QDate::isLeapYear(
int y)
1936 return QGregorianCalendar::leapTest(y);
1940
1941
1942
1943
1944
1947
1948
1949
1950
1951
1954
1955
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2004
2005
2006
2007
2008
2009
2010
2011
2014
2015
2016
2017
2018
2019
2020
2021
2023QTime::QTime(
int h,
int m,
int s,
int ms)
2025 setHMS(h, m, s, ms);
2030
2031
2032
2033
2034
2035
2036
2037
2040
2041
2042
2043
2044
2046bool QTime::isValid()
const
2048 return mds > NullTime && mds < MSECS_PER_DAY;
2053
2054
2055
2056
2057
2058
2060int QTime::hour()
const
2065 return ds() / MSECS_PER_HOUR;
2069
2070
2071
2072
2073
2074
2076int QTime::minute()
const
2081 return (ds() % MSECS_PER_HOUR) / MSECS_PER_MIN;
2085
2086
2087
2088
2089
2090
2092int QTime::second()
const
2097 return (ds() / MSECS_PER_SEC) % SECS_PER_MIN;
2101
2102
2103
2104
2105
2106
2108int QTime::msec()
const
2113 return ds() % MSECS_PER_SEC;
2116#if QT_CONFIG(datestring)
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2141QString QTime::toString(Qt::DateFormat format)
const
2147 case Qt::ISODateWithMs:
2148 return QString::asprintf(
"%02d:%02d:%02d.%03d", hour(), minute(), second(), msec());
2149 case Qt::RFC2822Date:
2153 return QString::asprintf(
"%02d:%02d:%02d", hour(), minute(), second());
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2265QString QTime::toString(QStringView format)
const
2267 return QLocale::c().toString(*
this, format);
2272
2273
2274
2275
2276
2277
2278
2279
2280
2282bool QTime::setHMS(
int h,
int m,
int s,
int ms)
2284 if (!isValid(h,m,s,ms)) {
2288 mds = ((h * MINS_PER_HOUR + m) * SECS_PER_MIN + s) * MSECS_PER_SEC + ms;
2289 Q_ASSERT(mds >= 0 && mds < MSECS_PER_DAY);
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2308QTime QTime::addSecs(
int s)
const
2311 return addMSecs(s * MSECS_PER_SEC);
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2329int QTime::secsTo(QTime t)
const
2331 if (!isValid() || !t.isValid())
2335 int ourSeconds = ds() / MSECS_PER_SEC;
2336 int theirSeconds = t.ds() / MSECS_PER_SEC;
2337 return theirSeconds - ourSeconds;
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2352QTime QTime::addMSecs(
int ms)
const
2356 t.mds = QRoundingDown::qMod<MSECS_PER_DAY>(ds() + ms);
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2374int QTime::msecsTo(QTime t)
const
2376 if (!isValid() || !t.isValid())
2378 return t.ds() - ds();
2383
2384
2385
2386
2389
2390
2391
2392
2395
2396
2397
2398
2401
2402
2403
2404
2405
2408
2409
2410
2411
2414
2415
2416
2417
2418
2421
2422
2423
2424
2425
2426
2427
2428
2429
2432
2433
2434
2435
2436
2437
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2454#if QT_CONFIG(datestring)
2456static QTime fromIsoTimeString(QStringView string, Qt::DateFormat format,
bool *isMidnight24)
2458 Q_ASSERT(format == Qt::TextDate || format == Qt::ISODate || format == Qt::ISODateWithMs);
2460 *isMidnight24 =
false;
2466 const qsizetype dot = string.indexOf(u'.'), comma = string.indexOf(u',');
2468 tail = string.sliced(dot + 1);
2469 if (tail.indexOf(u'.') != -1)
2471 string = string.first(dot);
2472 }
else if (comma != -1) {
2473 tail = string.sliced(comma + 1);
2474 string = string.first(comma);
2476 if (tail.indexOf(u',') != -1)
2479 const ParsedInt frac = readInt(tail);
2481 if (tail.isEmpty() ? dot != -1 || comma != -1 : !frac.ok())
2483 Q_ASSERT(frac.ok() ^ tail.isEmpty());
2484 double fraction = frac.ok() ? frac.result * std::pow(0.1, tail.size()) : 0.0;
2486 const qsizetype size = string.size();
2487 if (size < 2 || size > 8)
2490 ParsedInt hour = readInt(string.first(2));
2491 if (!hour.ok() || hour.result > (format == Qt::TextDate ? 23 : 24))
2495 if (string.size() > 2) {
2496 if (string[2] == u':' && string.size() > 4)
2497 minute = readInt(string.sliced(3, 2));
2498 if (!minute.ok() || minute.result >= MINS_PER_HOUR)
2500 }
else if (format == Qt::TextDate) {
2502 }
else if (frac.ok()) {
2503 Q_ASSERT(!(fraction < 0.0) && fraction < 1.0);
2504 fraction *= MINS_PER_HOUR;
2505 minute.result = qulonglong(fraction);
2506 fraction -= minute.result;
2510 if (string.size() > 5) {
2511 if (string[5] == u':' && string.size() == 8)
2512 second = readInt(string.sliced(6, 2));
2513 if (!second.ok() || second.result >= SECS_PER_MIN)
2515 }
else if (frac.ok()) {
2516 if (format == Qt::TextDate)
2518 Q_ASSERT(!(fraction < 0.0) && fraction < 1.0);
2519 fraction *= SECS_PER_MIN;
2520 second.result = qulonglong(fraction);
2521 fraction -= second.result;
2524 Q_ASSERT(!(fraction < 0.0) && fraction < 1.0);
2526 int msec = frac.ok() ? qRound(MSECS_PER_SEC * fraction) : 0;
2528 if (msec == MSECS_PER_SEC) {
2531 if (isMidnight24 || hour.result < 23 || minute.result < 59 || second.result < 59) {
2533 if (++second.result == SECS_PER_MIN) {
2535 if (++minute.result == MINS_PER_HOUR) {
2544 msec = MSECS_PER_SEC - 1;
2549 if (hour.result == 24 && minute.result == 0 && second.result == 0 && msec == 0) {
2550 Q_ASSERT(format != Qt::TextDate);
2552 *isMidnight24 =
true;
2556 return QTime(hour.result, minute.result, second.result, msec);
2560
2561
2562
2563
2564
2565
2566
2569
2570
2571
2572QTime QTime::fromString(QStringView string, Qt::DateFormat format)
2574 if (string.isEmpty())
2578 case Qt::RFC2822Date:
2579 return rfcDateImpl(string).time;
2581 case Qt::ISODateWithMs:
2584 return fromIsoTimeString(string, format,
nullptr);
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2667
2668
2669
2670
2673
2674
2675
2676QTime QTime::fromString(
const QString &string, QStringView format)
2679#if QT_CONFIG(datetimeparser)
2680 QDateTimeParser dt(QMetaType::QTime, QDateTimeParser::FromString, QCalendar());
2681 dt.setDefaultLocale(QLocale::c());
2682 if (dt.parseFormat(format))
2683 dt.fromString(string,
nullptr, &time);
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2707bool QTime::isValid(
int h,
int m,
int s,
int ms)
2709 return (uint(h) < 24 && uint(m) < MINS_PER_HOUR && uint(s) < SECS_PER_MIN
2710 && uint(ms) < MSECS_PER_SEC);
2714
2715
2724 return JULIAN_DAY_FOR_EPOCH + QRoundingDown::qDiv<MSECS_PER_DAY>(msecs);
2729 return QDate::fromJulianDay(msecsToJulianDay(msecs));
2734 return QTime::fromMSecsSinceStartOfDay(QRoundingDown::qMod<MSECS_PER_DAY>(msecs));
2741 return qMulOverflow(days, std::integral_constant<qint64, MSECS_PER_DAY>(), sumMillis)
2742 || qAddOverflow(*sumMillis, millisInDay, sumMillis);
2748 qint64 days = date.toJulianDay() - JULIAN_DAY_FOR_EPOCH;
2749 qint64 msecs, dayms = time.msecsSinceStartOfDay();
2750 if (days < 0 && dayms > 0) {
2752 dayms -= MSECS_PER_DAY;
2754 if (daysAndMillisOverflow(days, dayms, &msecs)) {
2755 using Bound = std::numeric_limits<qint64>;
2756 return days < 0 ? Bound::min() : Bound::max();
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2780 static const auto bounds = QLocalTime::computeSystemMillisRange();
2781 return (bounds.minClip || millis >= bounds.min - slack)
2782 && (bounds.maxClip || millis <= bounds.max + slack);
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2803#if defined(Q_OS_WIN) || defined(Q_OS_WASM)
2804 static constexpr int forLeapEarly[] = { 1984, 1996, 1980, 1992, 1976, 1988, 1972 };
2805 static constexpr int regularEarly[] = { 1978, 1973, 1974, 1975, 1970, 1971, 1977 };
2807 static constexpr int forLeapEarly[] = { 1928, 1912, 1924, 1908, 1920, 1904, 1916 };
2808 static constexpr int regularEarly[] = { 1905, 1906, 1907, 1902, 1903, 1909, 1910 };
2810 static constexpr int forLeapLate[] = { 2012, 2024, 2036, 2020, 2032, 2016, 2028 };
2811 static constexpr int regularLate[] = { 2034, 2035, 2030, 2031, 2037, 2027, 2033 };
2812 const int dow = QGregorianCalendar::yearStartWeekDay(year);
2813 Q_ASSERT(dow == QDate(year, 1, 1).dayOfWeek());
2814 const int res = (QGregorianCalendar::leapTest(year)
2815 ? (year < 1970 ? forLeapEarly : forLeapLate)
2816 : (year < 1970 ? regularEarly : regularLate))[dow == 7 ? 0 : dow];
2817 Q_ASSERT(QDate(res, 1, 1).dayOfWeek() == dow);
2818 Q_ASSERT(QDate(res, 12, 31).dayOfWeek() == QDate(year, 12, 31).dayOfWeek());
2823QDateTimePrivate::ZoneState QDateTimePrivate::expressUtcAsLocal(qint64 utcMSecs)
2825 ZoneState result{utcMSecs};
2827 if (millisInSystemRange(utcMSecs)) {
2828 result = QLocalTime::utcToLocal(utcMSecs);
2835#if QT_CONFIG(timezone)
2836 if (
const auto sys = QTimeZone::systemTimeZone(); sys.isValid()) {
2837 result.offset = sys.d->offsetFromUtc(utcMSecs);
2838 if (result.offset != QTimeZonePrivate::invalidSeconds()) {
2839 if (qAddOverflow(utcMSecs, result.offset * MSECS_PER_SEC, &result.when))
2841 result.dst = sys.d->isDaylightTime(utcMSecs) ? DaylightTime : StandardTime;
2842 result.valid =
true;
2851 const qint64 jd = msecsToJulianDay(utcMSecs);
2852 const auto ymd = QGregorianCalendar::partsFromJulian(jd);
2853 qint64 diffMillis, fakeUtc;
2854 const auto fakeJd = QGregorianCalendar::julianFromParts(systemTimeYearMatching(ymd.year),
2855 ymd.month, ymd.day);
2856 if (Q_UNLIKELY(!fakeJd
2857 || qMulOverflow(jd - *fakeJd, std::integral_constant<qint64, MSECS_PER_DAY>(),
2859 || qSubOverflow(utcMSecs, diffMillis, &fakeUtc))) {
2863 result = QLocalTime::utcToLocal(fakeUtc);
2865 if (!result.valid || qAddOverflow(result.when, diffMillis, &result.when)) {
2868 result.when = utcMSecs;
2869 result.valid =
false;
2880 qint64 jd = msecsToJulianDay(millis);
2881 auto ymd = QGregorianCalendar::partsFromJulian(jd);
2882 const auto fakeJd = QGregorianCalendar::julianFromParts(systemTimeYearMatching(ymd.year),
2883 ymd.month, ymd.day);
2884 result.good = fakeJd && !daysAndMillisOverflow(*fakeJd - jd, millis, &result.shifted);
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2946 case QDateTime::TransitionResolution::RelativeToBefore:
2947 return QDateTimePrivate::GapUseAfter | QDateTimePrivate::FoldUseBefore;
2948 case QDateTime::TransitionResolution::RelativeToAfter:
2949 return QDateTimePrivate::GapUseBefore | QDateTimePrivate::FoldUseAfter;
2950 case QDateTime::TransitionResolution::PreferBefore:
2951 return QDateTimePrivate::GapUseBefore | QDateTimePrivate::FoldUseBefore;
2952 case QDateTime::TransitionResolution::PreferAfter:
2953 return QDateTimePrivate::GapUseAfter | QDateTimePrivate::FoldUseAfter;
2954 case QDateTime::TransitionResolution::PreferStandard:
2955 return QDateTimePrivate::GapUseBefore
2956 | QDateTimePrivate::FoldUseAfter
2957 | QDateTimePrivate::FlipForReverseDst;
2958 case QDateTime::TransitionResolution::PreferDaylightSaving:
2959 return QDateTimePrivate::GapUseAfter
2960 | QDateTimePrivate::FoldUseBefore
2961 | QDateTimePrivate::FlipForReverseDst;
2962 case QDateTime::TransitionResolution::Reject:
break;
2970 return toTransitionOptions(dst == QDateTimePrivate::DaylightTime
2971 ? QDateTime::TransitionResolution::PreferDaylightSaving
2972 : QDateTime::TransitionResolution::PreferStandard);
2975QString QDateTimePrivate::localNameAtMillis(qint64 millis, DaylightStatus dst)
2977 const QDateTimePrivate::TransitionOptions resolve = toTransitionOptions(dst);
2978 QString abbreviation;
2979 if (millisInSystemRange(millis, MSECS_PER_DAY)) {
2980 abbreviation = QLocalTime::localTimeAbbbreviationAt(millis, resolve);
2981 if (!abbreviation.isEmpty())
2982 return abbreviation;
2986#if QT_CONFIG(timezone)
2988 const auto sys = QTimeZone::systemTimeZone();
2989 if (sys.isValid()) {
2990 ZoneState state = zoneStateAtMillis(sys, millis, resolve);
2992 return sys.d->abbreviation(state.when - state.offset * MSECS_PER_SEC);
2998 auto fake = millisToWithinRange(millis);
2999 if (Q_LIKELY(fake.good))
3000 return QLocalTime::localTimeAbbbreviationAt(fake.shifted, resolve);
3007QDateTimePrivate::ZoneState QDateTimePrivate::localStateAtMillis(
3008 qint64 millis, QDateTimePrivate::TransitionOptions resolve)
3012 if (millisInSystemRange(millis, MSECS_PER_DAY)) {
3013 auto result = QLocalTime::mapLocalTime(millis, resolve);
3019#if QT_CONFIG(timezone)
3021 const auto sys = QTimeZone::systemTimeZone();
3023 return zoneStateAtMillis(sys, millis, resolve);
3028 auto fake = millisToWithinRange(millis);
3029 if (Q_LIKELY(fake.good)) {
3030 auto result = QLocalTime::mapLocalTime(fake.shifted, resolve);
3033 if (Q_UNLIKELY(qAddOverflow(result.when, millis - fake.shifted, &adjusted))) {
3034 using Bound = std::numeric_limits<qint64>;
3035 adjusted = millis < fake.shifted ? Bound::min() : Bound::max();
3037 result.when = adjusted;
3039 result.when = millis;
3047#if QT_CONFIG(timezone)
3051QDateTimePrivate::ZoneState QDateTimePrivate::zoneStateAtMillis(
3052 const QTimeZone &zone, qint64 millis, QDateTimePrivate::TransitionOptions resolve)
3054 Q_ASSERT(zone.isValid());
3055 Q_ASSERT(zone.timeSpec() == Qt::TimeZone);
3056 return zone.d->stateAtZoneTime(millis, resolve);
3061 QDateTimePrivate::TransitionOptions resolve)
3063 if (zone.timeSpec() == Qt::LocalTime)
3064 return QDateTimePrivate::localStateAtMillis(millis, resolve);
3065#if QT_CONFIG(timezone)
3066 if (zone.timeSpec() == Qt::TimeZone && zone.isValid())
3067 return QDateTimePrivate::zoneStateAtMillis(zone, millis, resolve);
3074 return spec == Qt::LocalTime || spec == Qt::UTC;
3079 if constexpr (!QDateTimeData::CanBeSmall)
3083 sd.msecs = qintptr(msecs);
3084 return sd.msecs == msecs;
3087static constexpr inline
3090 status &= ~QDateTimePrivate::TimeSpecMask;
3091 status |= QDateTimePrivate::StatusFlags::fromInt(
int(spec) << QDateTimePrivate::TimeSpecShift);
3097 return Qt::TimeSpec((status & QDateTimePrivate::TimeSpecMask).toInt() >> QDateTimePrivate::TimeSpecShift);
3104 sf &= ~QDateTimePrivate::DaylightMask;
3105 if (status == QDateTimePrivate::DaylightTime) {
3106 sf |= QDateTimePrivate::SetToDaylightTime;
3107 }
else if (status == QDateTimePrivate::StandardTime) {
3108 sf |= QDateTimePrivate::SetToStandardTime;
3114static constexpr inline
3117 if (status.testFlag(QDateTimePrivate::SetToDaylightTime))
3118 return QDateTimePrivate::DaylightTime;
3119 if (status.testFlag(QDateTimePrivate::SetToStandardTime))
3120 return QDateTimePrivate::StandardTime;
3121 return QDateTimePrivate::UnknownDaylightTime;
3129 return qintptr(d.d) >> 8;
3139 return QDateTimePrivate::StatusFlag(qintptr(d.d) & 0xFF);
3146 return extractSpec(getStatus(d));
3150
3151
3152
3153
3156 const auto status = getStatus(a);
3157 if (status != getStatus(b))
3161 switch (extractSpec(status)) {
3168
3169
3170
3171
3172 case Qt::OffsetFromUTC:
3173 Q_ASSERT(!a.isShort() && !b.isShort());
3174 return a->m_offsetFromUtc == b->m_offsetFromUtc;
3176 Q_UNREACHABLE_RETURN(
false);
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3193 constexpr quint64 UtcOffsetMillisRange
3194 = quint64(QTimeZone::MaxUtcOffsetSecs - QTimeZone::MinUtcOffsetSecs) * MSECS_PER_SEC;
3196 return qSubOverflow(leftMillis, rightMillis, &gap) || QtPrivate::qUnsignedAbs(gap) > UtcOffsetMillisRange;
3201 QDateTimePrivate::TransitionOptions resolve)
3203 Q_ASSERT(zone.timeSpec() == Qt::TimeZone || zone.timeSpec() == Qt::LocalTime);
3204 auto status = getStatus(d);
3205 Q_ASSERT(extractSpec(status) == zone.timeSpec());
3206 int offsetFromUtc = 0;
3208
3209
3210
3211
3212
3213
3214
3215
3218 if (!status.testFlags(QDateTimePrivate::ValidDate | QDateTimePrivate::ValidTime)) {
3219 status.setFlag(QDateTimePrivate::ValidDateTime,
false);
3223 qint64 msecs = getMSecs(d);
3224 QDateTimePrivate::ZoneState state = stateAtMillis(zone, msecs, resolve);
3225 Q_ASSERT(!state.valid || (state.offset >= -SECS_PER_DAY && state.offset <= SECS_PER_DAY));
3226 if (state.dst == QDateTimePrivate::UnknownDaylightTime) {
3227 status.setFlag(QDateTimePrivate::ValidDateTime,
false);
3228 }
else if (state.valid) {
3229 status = mergeDaylightStatus(status, state.dst);
3230 offsetFromUtc = state.offset;
3231 status.setFlag(QDateTimePrivate::ValidDateTime,
true);
3232 if (Q_UNLIKELY(msecs != state.when)) {
3234 if (status.testFlag(QDateTimePrivate::ShortData)) {
3235 if (msecsCanBeSmall(state.when)) {
3236 d.data.msecs = qintptr(state.when);
3239 status.setFlag(QDateTimePrivate::ShortData,
false);
3243 if (!status.testFlag(QDateTimePrivate::ShortData))
3244 d->m_msecs = state.when;
3247 status.setFlag(QDateTimePrivate::ValidDateTime,
false);
3251 if (status.testFlag(QDateTimePrivate::ShortData)) {
3252 d.data.status = status.toInt();
3254 d->m_status = status;
3255 d->m_offsetFromUtc = offsetFromUtc;
3262 auto status = getStatus(d);
3263 Q_ASSERT(QTimeZone::isUtcOrFixedOffset(extractSpec(status)));
3264 status.setFlag(QDateTimePrivate::ValidDateTime,
3265 status.testFlags(QDateTimePrivate::ValidDate | QDateTimePrivate::ValidTime));
3267 if (status.testFlag(QDateTimePrivate::ShortData))
3268 d.data.status = status.toInt();
3270 d->m_status = status;
3276 auto spec = extractSpec(getStatus(d));
3278 case Qt::OffsetFromUTC:
3287 refreshZonedDateTime(d, d.timeZone(), toTransitionOptions(resolve));
3293 QDateTime::TransitionResolution resolve)
3295 Qt::TimeSpec spec = zone.timeSpec();
3296 auto status = mergeSpec(getStatus(d), spec);
3297 bool reuse = d.isShort();
3302 Q_ASSERT(zone.fixedSecondsAheadOfUtc() == 0);
3304 case Qt::OffsetFromUTC:
3306 offset = zone.fixedSecondsAheadOfUtc();
3316 status &= ~(QDateTimePrivate::ValidDateTime | QDateTimePrivate::DaylightMask);
3318 d.data.status = status.toInt();
3321 d->m_status = status & ~QDateTimePrivate::ShortData;
3322 d->m_offsetFromUtc = offset;
3323#if QT_CONFIG(timezone)
3324 if (spec == Qt::TimeZone)
3325 d->m_timeZone = zone;
3329 if (QTimeZone::isUtcOrFixedOffset(spec))
3332 refreshZonedDateTime(d, zone, toTransitionOptions(resolve));
3338 if (!time.isValid() && date.isValid())
3339 time = QTime::fromMSecsSinceStartOfDay(0);
3341 QDateTimePrivate::StatusFlags newStatus = { };
3345 if (date.isValid()) {
3346 days = date.toJulianDay() - JULIAN_DAY_FOR_EPOCH;
3347 newStatus = QDateTimePrivate::ValidDate;
3352 if (time.isValid()) {
3353 ds = time.msecsSinceStartOfDay();
3354 newStatus |= QDateTimePrivate::ValidTime;
3356 Q_ASSERT(ds < MSECS_PER_DAY);
3359 if (days < 0 && ds > 0) {
3361 ds -= MSECS_PER_DAY;
3366 if (daysAndMillisOverflow(days, qint64(ds), &msecs)) {
3367 newStatus = QDateTimePrivate::StatusFlags{};
3372 if (msecsCanBeSmall(msecs)) {
3374 d.data.msecs = qintptr(msecs);
3375 d.data.status &= ~(QDateTimePrivate::ValidityMask | QDateTimePrivate::DaylightMask).toInt();
3376 d.data.status |= newStatus.toInt();
3385 d->m_status &= ~(QDateTimePrivate::ValidityMask | QDateTimePrivate::DaylightMask);
3386 d->m_status |= newStatus;
3392 auto status = getStatus(d);
3393 const qint64 msecs = getMSecs(d);
3394 const auto dayMilli = QRoundingDown::qDivMod<MSECS_PER_DAY>(msecs);
3395 return { status.testFlag(QDateTimePrivate::ValidDate)
3396 ? QDate::fromJulianDay(JULIAN_DAY_FOR_EPOCH + dayMilli.quotient)
3398 status.testFlag(QDateTimePrivate::ValidTime)
3399 ? QTime::fromMSecsSinceStartOfDay(dayMilli.remainder)
3404
3405
3407inline QDateTime::Data::Data()
noexcept
3412 quintptr value = mergeSpec(QDateTimePrivate::ShortData, Qt::LocalTime).toInt();
3413 d =
reinterpret_cast<QDateTimePrivate *>(value);
3416inline QDateTime::Data::Data(
const QTimeZone &zone)
3418 Qt::TimeSpec spec = zone.timeSpec();
3419 if (CanBeSmall && Q_LIKELY(specCanBeSmall(spec))) {
3420 quintptr value = mergeSpec(QDateTimePrivate::ShortData, spec).toInt();
3421 d =
reinterpret_cast<QDateTimePrivate *>(value);
3422 Q_ASSERT(isShort());
3425 d =
new QDateTimePrivate;
3427 d->m_status = mergeSpec({}, spec);
3428 if (spec == Qt::OffsetFromUTC)
3429 d->m_offsetFromUtc = zone.fixedSecondsAheadOfUtc();
3430 else if (spec == Qt::TimeZone)
3431 d->m_timeZone = zone;
3432 Q_ASSERT(!isShort());
3436inline QDateTime::Data::Data(
const Data &other)
noexcept
3441 if (specCanBeSmall(extractSpec(d->m_status)) && msecsCanBeSmall(d->m_msecs)) {
3443 sd.msecs = qintptr(d->m_msecs);
3444 sd.status = (d->m_status | QDateTimePrivate::ShortData).toInt();
3453inline QDateTime::Data::Data(Data &&other)
noexcept
3458 Q_ASSERT(dummy.isShort());
3459 other.data = dummy.data;
3462inline QDateTime::Data &QDateTime::Data::operator=(
const Data &other)
noexcept
3464 if (isShort() ? data == other.data : d == other.d)
3469 if (!other.isShort()) {
3471 if (specCanBeSmall(extractSpec(other.d->m_status)) && msecsCanBeSmall(other.d->m_msecs)) {
3473 sd.msecs = qintptr(other.d->m_msecs);
3474 sd.status = (other.d->m_status | QDateTimePrivate::ShortData).toInt();
3482 if (!(quintptr(x) & QDateTimePrivate::ShortData) && !x->ref.deref())
3487inline QDateTime::Data::~Data()
3489 if (!isShort() && !d->ref.deref())
3493inline bool QDateTime::Data::isShort()
const
3495 bool b = quintptr(d) & QDateTimePrivate::ShortData;
3498 Q_ASSERT(b || !d->m_status.testFlag(QDateTimePrivate::ShortData));
3502 if constexpr (CanBeSmall)
3504 return Q_UNLIKELY(b);
3507inline void QDateTime::Data::detach()
3509 QDateTimePrivate *x;
3510 bool wasShort = isShort();
3513 x =
new QDateTimePrivate;
3514 x->m_status = QDateTimePrivate::StatusFlags::fromInt(data.status) & ~QDateTimePrivate::ShortData;
3515 x->m_msecs = data.msecs;
3517 if (d->ref.loadRelaxed() == 1)
3520 x =
new QDateTimePrivate(*d);
3523 x->ref.storeRelaxed(1);
3524 if (!wasShort && !d->ref.deref())
3529void QDateTime::Data::invalidate()
3532 data.status &= ~
int(QDateTimePrivate::ValidityMask);
3535 d->m_status &= ~QDateTimePrivate::ValidityMask;
3539QTimeZone QDateTime::Data::timeZone()
const
3541 switch (getSpec(*
this)) {
3543 return QTimeZone::UTC;
3544 case Qt::OffsetFromUTC:
3545 return QTimeZone::fromSecondsAheadOfUtc(d->m_offsetFromUtc);
3547#if QT_CONFIG(timezone)
3548 if (d->m_timeZone.isValid())
3549 return d->m_timeZone;
3553 return QTimeZone::LocalTime;
3558inline const QDateTimePrivate *QDateTime::Data::operator->()
const
3560 Q_ASSERT(!isShort());
3564inline QDateTimePrivate *QDateTime::Data::operator->()
3567 Q_ASSERT(!isShort());
3568 Q_ASSERT(d->ref.loadRelaxed() == 1);
3573
3574
3577QDateTime::Data QDateTimePrivate::create(QDate toDate, QTime toTime,
const QTimeZone &zone,
3578 QDateTime::TransitionResolution resolve)
3580 QDateTime::Data result(zone);
3581 setDateTime(result, toDate, toTime);
3582 if (zone.isUtcOrFixedOffset())
3583 refreshSimpleDateTime(result);
3585 refreshZonedDateTime(result, zone, toTransitionOptions(resolve));
3590
3591
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3970
3971
3972
3973
3974
3975
3976QDateTime::QDateTime()
noexcept
3978#if QT_VERSION >= QT_VERSION_CHECK(7
, 0
, 0
) || defined(QT_BOOTSTRAPPED) || QT_POINTER_SIZE == 8
3979 static_assert(
sizeof(ShortData) ==
sizeof(qint64));
3980 static_assert(
sizeof(Data) ==
sizeof(qint64));
3982 static_assert(
sizeof(ShortData) >=
sizeof(
void*),
"oops, Data::swap() is broken!");
3985#if QT_DEPRECATED_SINCE(6
, 9
)
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006QDateTime::QDateTime(QDate date, QTime time, Qt::TimeSpec spec,
int offsetSeconds)
4007 : d(QDateTimePrivate::create(date, time, asTimeZone(spec, offsetSeconds,
"QDateTime"),
4008 TransitionResolution::LegacyBehavior))
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4030QDateTime::QDateTime(QDate date, QTime time,
const QTimeZone &timeZone, TransitionResolution resolve)
4031 : d(QDateTimePrivate::create(date, time, timeZone, resolve))
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4048QDateTime::QDateTime(QDate date, QTime time, TransitionResolution resolve)
4049 : d(QDateTimePrivate::create(date, time, QTimeZone::LocalTime, resolve))
4054
4055
4056QDateTime::QDateTime(
const QDateTime &other)
noexcept
4062
4063
4064
4065
4066QDateTime::QDateTime(QDateTime &&other)
noexcept
4067 : d(std::move(other.d))
4072
4073
4074QDateTime::~QDateTime()
4079
4080
4082QDateTime &QDateTime::operator=(
const QDateTime &other)
noexcept
4088
4089
4090
4091
4094
4095
4096
4097
4098
4100bool QDateTime::isNull()
const
4103 return !getStatus(d).testAnyFlag(QDateTimePrivate::ValidityMask);
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4120bool QDateTime::isValid()
const
4122 return getStatus(d).testFlag(QDateTimePrivate::ValidDateTime);
4126
4127
4128
4129
4131QDate QDateTime::date()
const
4133 return getStatus(d).testFlag(QDateTimePrivate::ValidDate) ? msecsToDate(getMSecs(d)) : QDate();
4137
4138
4139
4140
4142QTime QDateTime::time()
const
4144 return getStatus(d).testFlag(QDateTimePrivate::ValidTime) ? msecsToTime(getMSecs(d)) : QTime();
4148
4149
4150
4151
4152
4153
4154
4155
4156
4158Qt::TimeSpec QDateTime::timeSpec()
const
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4177QTimeZone QDateTime::timeRepresentation()
const
4179 return d.timeZone();
4182#if QT_CONFIG(timezone)
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4198QTimeZone QDateTime::timeZone()
const
4200 return d.timeZone().asBackendZone();
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4226int QDateTime::offsetFromUtc()
const
4228 const auto status = getStatus(d);
4229 if (!status.testFlags(QDateTimePrivate::ValidDate | QDateTimePrivate::ValidTime))
4233 return d->m_offsetFromUtc;
4235 auto spec = extractSpec(status);
4236 if (spec == Qt::LocalTime) {
4238 const auto resolve = toTransitionOptions(extractDaylightStatus(status));
4239 return QDateTimePrivate::localStateAtMillis(getMSecs(d), resolve).offset;
4242 Q_ASSERT(spec == Qt::UTC);
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4267QString QDateTime::timeZoneAbbreviation()
const
4272 switch (getSpec(d)) {
4275 case Qt::OffsetFromUTC:
4276 return "UTC"_L1 + toOffsetString(Qt::ISODate, d->m_offsetFromUtc);
4278#if !QT_CONFIG(timezone)
4281 Q_ASSERT(d->m_timeZone.isValid());
4282 return d->m_timeZone.abbreviation(*
this);
4285#if defined(Q_OS_WIN) && QT_CONFIG(timezone)
4287 if (QString sys = QTimeZone::systemTimeZone().abbreviation(*
this); !sys.isEmpty())
4291 return QDateTimePrivate::localNameAtMillis(getMSecs(d),
4292 extractDaylightStatus(getStatus(d)));
4298
4299
4300
4301
4302
4303
4304
4305
4306
4308bool QDateTime::isDaylightTime()
const
4313 switch (getSpec(d)) {
4315 case Qt::OffsetFromUTC:
4318#if !QT_CONFIG(timezone)
4321 Q_ASSERT(d->m_timeZone.isValid());
4322 if (
auto dst = extractDaylightStatus(getStatus(d));
4323 dst != QDateTimePrivate::UnknownDaylightTime) {
4324 return dst == QDateTimePrivate::DaylightTime;
4326 return d->m_timeZone.d->isDaylightTime(toMSecsSinceEpoch());
4328 case Qt::LocalTime: {
4329 auto dst = extractDaylightStatus(getStatus(d));
4330 if (dst == QDateTimePrivate::UnknownDaylightTime) {
4331 dst = QDateTimePrivate::localStateAtMillis(
4332 getMSecs(d), toTransitionOptions(TransitionResolution::LegacyBehavior)).dst;
4334 return dst == QDateTimePrivate::DaylightTime;
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4355void QDateTime::setDate(QDate date, TransitionResolution resolve)
4357 setDateTime(d, date, time());
4358 checkValidDateTime(d, resolve);
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4380void QDateTime::setTime(QTime time, TransitionResolution resolve)
4382 setDateTime(d, date(), time);
4383 checkValidDateTime(d, resolve);
4386#if QT_DEPRECATED_SINCE(6
, 9
)
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4405void QDateTime::setTimeSpec(Qt::TimeSpec spec)
4407 reviseTimeZone(d, asTimeZone(spec, 0,
"QDateTime::setTimeSpec"),
4408 TransitionResolution::LegacyBehavior);
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4427void QDateTime::setOffsetFromUtc(
int offsetSeconds)
4429 reviseTimeZone(d, QTimeZone::fromSecondsAheadOfUtc(offsetSeconds),
4430 TransitionResolution::Reject);
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4454void QDateTime::setTimeZone(
const QTimeZone &toZone, TransitionResolution resolve)
4456 reviseTimeZone(d, toZone, resolve);
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474qint64 QDateTime::toMSecsSinceEpoch()
const
4481 const auto status = getStatus(d);
4482 if (!status.testFlags(QDateTimePrivate::ValidDate | QDateTimePrivate::ValidTime))
4485 switch (extractSpec(status)) {
4489 case Qt::OffsetFromUTC:
4490 Q_ASSERT(!d.isShort());
4491 return d->m_msecs - d->m_offsetFromUtc * MSECS_PER_SEC;
4494 if (status.testFlag(QDateTimePrivate::ShortData)) {
4496 const auto resolve = toTransitionOptions(extractDaylightStatus(getStatus(d)));
4497 const auto state = QDateTimePrivate::localStateAtMillis(getMSecs(d), resolve);
4498 return state.when - state.offset * MSECS_PER_SEC;
4501 return d->m_msecs - d->m_offsetFromUtc * MSECS_PER_SEC;
4504 Q_ASSERT(!d.isShort());
4505#if QT_CONFIG(timezone)
4507 if (d->m_timeZone.isValid())
4508 return d->m_msecs - d->m_offsetFromUtc * MSECS_PER_SEC;
4512 Q_UNREACHABLE_RETURN(0);
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530qint64 QDateTime::toSecsSinceEpoch()
const
4532 return toMSecsSinceEpoch() / MSECS_PER_SEC;
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550void QDateTime::setMSecsSinceEpoch(qint64 msecs)
4552 auto status = getStatus(d);
4553 const auto spec = extractSpec(status);
4554 Q_ASSERT(specCanBeSmall(spec) || !d.isShort());
4555 QDateTimePrivate::ZoneState state(msecs);
4557 status &= ~QDateTimePrivate::ValidityMask;
4558 if (QTimeZone::isUtcOrFixedOffset(spec)) {
4559 if (spec == Qt::OffsetFromUTC)
4560 state.offset = d->m_offsetFromUtc;
4561 if (!state.offset || !qAddOverflow(msecs, state.offset * MSECS_PER_SEC, &state.when))
4562 status |= QDateTimePrivate::ValidityMask;
4563 }
else if (spec == Qt::LocalTime) {
4564 state = QDateTimePrivate::expressUtcAsLocal(msecs);
4566 status = mergeDaylightStatus(status | QDateTimePrivate::ValidityMask, state.dst);
4567#if QT_CONFIG(timezone)
4568 }
else if (spec == Qt::TimeZone && (d.detach(), d->m_timeZone.isValid())) {
4569 const auto data = d->m_timeZone.d->data(msecs);
4570 if (Q_LIKELY(data.offsetFromUtc != QTimeZonePrivate::invalidSeconds())) {
4571 state.offset = data.offsetFromUtc;
4572 Q_ASSERT(state.offset >= -SECS_PER_DAY && state.offset <= SECS_PER_DAY);
4574 || !Q_UNLIKELY(qAddOverflow(msecs, state.offset * MSECS_PER_SEC, &state.when))) {
4575 d->m_status = mergeDaylightStatus(status | QDateTimePrivate::ValidityMask,
4576 data.daylightTimeOffset
4577 ? QDateTimePrivate::DaylightTime
4578 : QDateTimePrivate::StandardTime);
4579 d->m_msecs = state.when;
4580 d->m_offsetFromUtc = state.offset;
4586 Q_ASSERT(!status.testFlag(QDateTimePrivate::ValidDateTime)
4587 || (state.offset >= -SECS_PER_DAY && state.offset <= SECS_PER_DAY));
4589 if (msecsCanBeSmall(state.when) && d.isShort()) {
4591 d.data.msecs = qintptr(state.when);
4592 d.data.status = status.toInt();
4595 d->m_status = status & ~QDateTimePrivate::ShortData;
4596 d->m_msecs = state.when;
4597 d->m_offsetFromUtc = state.offset;
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612void QDateTime::setSecsSinceEpoch(qint64 secs)
4615 if (!qMulOverflow(secs, std::integral_constant<qint64, MSECS_PER_SEC>(), &msecs))
4616 setMSecsSinceEpoch(msecs);
4621#if QT_CONFIG(datestring)
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652QString QDateTime::toString(Qt::DateFormat format)
const
4659 case Qt::RFC2822Date:
4660 buf = QLocale::c().toString(*
this, u"dd MMM yyyy hh:mm:ss ");
4661 buf += toOffsetString(Qt::TextDate, offsetFromUtc());
4664 case Qt::TextDate: {
4665 const std::pair<QDate, QTime> p = getDateTime(d);
4666 buf = toStringTextDate(p.first);
4668 buf.insert(buf.lastIndexOf(u' '),
4669 u' ' + p.second.toString(Qt::TextDate));
4671 switch (timeSpec()) {
4674#if QT_CONFIG(timezone)
4676 buf += u' ' + d->m_timeZone.displayName(
4677 *
this, QTimeZone::OffsetName, QLocale::c());
4686 if (getSpec(d) == Qt::OffsetFromUTC)
4687 buf += toOffsetString(Qt::TextDate, offsetFromUtc());
4692 case Qt::ISODateWithMs: {
4693 const std::pair<QDate, QTime> p = getDateTime(d);
4694 buf = toStringIsoDate(p.first);
4697 buf += u'T' + p.second.toString(format);
4698 switch (getSpec(d)) {
4702 case Qt::OffsetFromUTC:
4704 buf += toOffsetString(Qt::ISODate, offsetFromUtc());
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757QString QDateTime::toString(QStringView format, QCalendar cal)
const
4759 return QLocale::c().toString(*
this, format, cal);
4764
4765
4766
4767QString QDateTime::toString(QStringView format)
const
4769 return QLocale::c().toString(*
this, format, QCalendar());
4773
4774
4775
4776QString QDateTime::toString(
const QString &format)
const
4778 return QLocale::c().toString(*
this, qToStringViewIgnoringNull(format), QCalendar());
4784 const QDateTimePrivate::TransitionOptions resolve = toTransitionOptions(
4785 forward ? QDateTime::TransitionResolution::RelativeToBefore
4786 : QDateTime::TransitionResolution::RelativeToAfter);
4787 auto status = getStatus(d);
4788 Q_ASSERT(status.testFlags(QDateTimePrivate::ValidDate | QDateTimePrivate::ValidTime
4789 | QDateTimePrivate::ValidDateTime));
4790 auto spec = extractSpec(status);
4791 if (QTimeZone::isUtcOrFixedOffset(spec)) {
4792 setDateTime(d, date, time);
4796 qint64 local = timeToMSecs(date, time);
4797 const QDateTimePrivate::ZoneState state = stateAtMillis(d.timeZone(), local, resolve);
4798 Q_ASSERT(state.valid || state.dst == QDateTimePrivate::UnknownDaylightTime);
4799 if (state.dst == QDateTimePrivate::UnknownDaylightTime)
4800 status.setFlag(QDateTimePrivate::ValidDateTime,
false);
4802 status = mergeDaylightStatus(status | QDateTimePrivate::ValidDateTime, state.dst);
4804 if (status & QDateTimePrivate::ShortData) {
4805 d.data.msecs = state.when;
4806 d.data.status = status.toInt();
4809 d->m_status = status;
4811 d->m_msecs = state.when;
4812 d->m_offsetFromUtc = state.offset;
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4832QDateTime QDateTime::addDays(qint64 ndays)
const
4837 QDateTime dt(*
this);
4838 std::pair<QDate, QTime> p = getDateTime(d);
4839 massageAdjustedDateTime(dt.d, p.first.addDays(ndays), p.second, ndays >= 0);
4844
4845
4846
4847
4848
4849
4850
4851
4854
4855
4856
4857
4858
4859
4860
4861
4864
4865
4866
4867
4868
4869
4870
4871
4874
4875
4876
4877
4878
4879
4880
4881
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4898QDateTime QDateTime::addMonths(
int nmonths)
const
4903 QDateTime dt(*
this);
4904 std::pair<QDate, QTime> p = getDateTime(d);
4905 massageAdjustedDateTime(dt.d, p.first.addMonths(nmonths), p.second, nmonths >= 0);
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4924QDateTime QDateTime::addYears(
int nyears)
const
4929 QDateTime dt(*
this);
4930 std::pair<QDate, QTime> p = getDateTime(d);
4931 massageAdjustedDateTime(dt.d, p.first.addYears(nyears), p.second, nyears >= 0);
4936
4937
4938
4939
4940
4941
4942
4943
4945QDateTime QDateTime::addSecs(qint64 s)
const
4948 if (qMulOverflow(s, std::integral_constant<qint64, MSECS_PER_SEC>(), &msecs))
4950 return addMSecs(msecs);
4954
4955
4956
4957
4958
4959
4960
4961
4962QDateTime QDateTime::addMSecs(qint64 msecs)
const
4967 QDateTime dt(*
this);
4968 switch (getSpec(d)) {
4972 if (!qAddOverflow(toMSecsSinceEpoch(), msecs, &msecs))
4973 dt.setMSecsSinceEpoch(msecs);
4978 case Qt::OffsetFromUTC:
4980 if (qAddOverflow(getMSecs(d), msecs, &msecs)) {
4982 }
else if (d.isShort() && msecsCanBeSmall(msecs)) {
4983 dt.d.data.msecs = qintptr(msecs);
4986 dt.d->m_msecs = msecs;
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5029qint64 QDateTime::daysTo(
const QDateTime &other)
const
5031 return date().daysTo(other.date());
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5051qint64 QDateTime::secsTo(
const QDateTime &other)
const
5053 return msecsTo(other) / MSECS_PER_SEC;
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5070qint64 QDateTime::msecsTo(
const QDateTime &other)
const
5072 if (!isValid() || !other.isValid())
5075 return other.toMSecsSinceEpoch() - toMSecsSinceEpoch();
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5147#if QT_DEPRECATED_SINCE(6
, 9
)
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5167QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec)
const
5169 return toTimeZone(asTimeZone(spec, 0,
"toTimeSpec"));
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5187QDateTime QDateTime::toOffsetFromUtc(
int offsetSeconds)
const
5189 return toTimeZone(QTimeZone::fromSecondsAheadOfUtc(offsetSeconds));
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203QDateTime QDateTime::toLocalTime()
const
5205 return toTimeZone(QTimeZone::LocalTime);
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219QDateTime QDateTime::toUTC()
const
5221 return toTimeZone(QTimeZone::UTC);
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5242QDateTime QDateTime::toTimeZone(
const QTimeZone &timeZone)
const
5244 if (timeRepresentation() == timeZone)
5248 QDateTime ret = *
this;
5249 ret.setTimeZone(timeZone);
5253 return fromMSecsSinceEpoch(toMSecsSinceEpoch(), timeZone);
5257
5258
5259
5260
5261
5262
5264bool QDateTime::equals(
const QDateTime &other)
const
5267 return !other.isValid();
5268 if (!other.isValid())
5271 const qint64 thisMs = getMSecs(d);
5272 const qint64 yourMs = getMSecs(other.d);
5273 if (usesSameOffset(d, other.d) || areFarEnoughApart(thisMs, yourMs))
5274 return thisMs == yourMs;
5277 return toMSecsSinceEpoch() == other.toMSecsSinceEpoch();
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5302
5303
5304
5305
5306
5307
5308
5309
5310
5315 return rhs.isValid() ? Qt::weak_ordering::less : Qt::weak_ordering::equivalent;
5318 return Qt::weak_ordering::greater;
5320 const qint64 lhms = getMSecs(lhs.d), rhms = getMSecs(rhs.d);
5321 if (usesSameOffset(lhs.d, rhs.d) || areFarEnoughApart(lhms, rhms))
5322 return Qt::compareThreeWay(lhms, rhms);
5325 return Qt::compareThreeWay(lhs.toMSecsSinceEpoch(), rhs.toMSecsSinceEpoch());
5329
5330
5331
5332
5333
5334
5335
5336
5337
5340
5341
5342
5343
5344
5345
5346
5347
5348
5351
5352
5353
5354
5355
5356
5357
5358
5361
5362
5363
5364
5365
5366
5367
5368
5369
5372
5373
5374
5375
5376
5377
5378
5379
5382
5383
5384
5385QDateTime QDateTime::currentDateTime()
5387 return currentDateTime(QTimeZone::LocalTime);
5391
5392
5393
5394
5395
5396
5397
5398
5400QDateTime QDateTime::currentDateTimeUtc()
5402 return currentDateTime(QTimeZone::UTC);
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5418
5419
5420
5421
5422
5423
5424
5425
5426
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5453
5454
5455
5456
5457
5458
5459QDateTime QDateTime::fromStdTimePoint(
5460 std::chrono::time_point<
5461 std::chrono::system_clock,
5462 std::chrono::milliseconds
5465 return fromMSecsSinceEpoch(time.time_since_epoch().count(), QTimeZone::UTC);
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5532#if defined(Q_OS_WIN)
5533static inline uint msecsFromDecomposed(
int hour,
int minute,
int sec,
int msec = 0)
5535 return MSECS_PER_HOUR * hour + MSECS_PER_MIN * minute + MSECS_PER_SEC * sec + msec;
5538QDate QDate::currentDate()
5542 return QDate(st.wYear, st.wMonth, st.wDay);
5545QTime QTime::currentTime()
5550 ct.setHMS(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
5554QDateTime QDateTime::currentDateTime(
const QTimeZone &zone)
5558 const Qt::TimeSpec spec = zone.timeSpec();
5566 QDate d(st.wYear, st.wMonth, st.wDay);
5567 QTime t(msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds));
5568 QDateTime utc(d, t, QTimeZone::UTC);
5569 return spec == Qt::UTC ? utc : utc.toTimeZone(zone);
5572qint64 QDateTime::currentMSecsSinceEpoch()
noexcept
5576 const qint64 daysAfterEpoch = QDate(1970, 1, 1).daysTo(QDate(st.wYear, st.wMonth, st.wDay));
5578 return msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds) +
5579 daysAfterEpoch * MSECS_PER_DAY;
5582qint64 QDateTime::currentSecsSinceEpoch()
noexcept
5586 const qint64 daysAfterEpoch = QDate(1970, 1, 1).daysTo(QDate(st.wYear, st.wMonth, st.wDay));
5588 return st.wHour * SECS_PER_HOUR + st.wMinute * SECS_PER_MIN + st.wSecond +
5589 daysAfterEpoch * SECS_PER_DAY;
5592#elif defined(Q_OS_UNIX)
5593QDate QDate::currentDate()
5595 return QDateTime::currentDateTime().date();
5598QTime QTime::currentTime()
5600 return QDateTime::currentDateTime().time();
5603QDateTime QDateTime::currentDateTime(
const QTimeZone &zone)
5605 return fromMSecsSinceEpoch(currentMSecsSinceEpoch(), zone);
5608qint64 QDateTime::currentMSecsSinceEpoch()
noexcept
5610 struct timespec when;
5611 if (clock_gettime(CLOCK_REALTIME, &when) == 0)
5612 return when.tv_sec * MSECS_PER_SEC + (when.tv_nsec + 500'000) / 1'000'000;
5613 Q_UNREACHABLE_RETURN(0);
5616qint64 QDateTime::currentSecsSinceEpoch()
noexcept
5618 struct timespec when;
5619 if (clock_gettime(CLOCK_REALTIME, &when) == 0)
5621 Q_UNREACHABLE_RETURN(0);
5624#error "What system is this?"
5627#if QT_DEPRECATED_SINCE(6
, 9
)
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, Qt::TimeSpec spec,
int offsetSeconds)
5653 return fromMSecsSinceEpoch(msecs,
5654 asTimeZone(spec, offsetSeconds,
"QDateTime::fromMSecsSinceEpoch"));
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs, Qt::TimeSpec spec,
int offsetSeconds)
5682 return fromSecsSinceEpoch(secs,
5683 asTimeZone(spec, offsetSeconds,
"QDateTime::fromSecsSinceEpoch"));
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs,
const QTimeZone &timeZone)
5703 reviseTimeZone(dt.d, timeZone, TransitionResolution::Reject);
5704 if (timeZone.isValid())
5705 dt.setMSecsSinceEpoch(msecs);
5710
5711
5712QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs)
5714 return fromMSecsSinceEpoch(msecs, QTimeZone::LocalTime);
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs,
const QTimeZone &timeZone)
5733 reviseTimeZone(dt.d, timeZone, TransitionResolution::Reject);
5734 if (timeZone.isValid())
5735 dt.setSecsSinceEpoch(secs);
5740
5741
5742QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs)
5744 return fromSecsSinceEpoch(secs, QTimeZone::LocalTime);
5747#if QT_CONFIG(datestring)
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5762
5763
5764
5765QDateTime QDateTime::fromString(QStringView string, Qt::DateFormat format)
5767 if (string.isEmpty())
5771 case Qt::RFC2822Date: {
5772 const ParsedRfcDateTime rfc = rfcDateImpl(string);
5774 if (!rfc.date.isValid() || !rfc.time.isValid())
5777 QDateTime dateTime(rfc.date, rfc.time, QTimeZone::UTC);
5778 dateTime.setTimeZone(QTimeZone::fromSecondsAheadOfUtc(rfc.utcOffset));
5782 case Qt::ISODateWithMs: {
5783 const int size = string.size();
5787 QDate date = QDate::fromString(string.first(10), Qt::ISODate);
5788 if (!date.isValid())
5791 return date.startOfDay();
5793 QTimeZone zone = QTimeZone::LocalTime;
5794 QStringView isoString = string.sliced(10);
5797 if (isoString.size() < 2
5798 || !(isoString.startsWith(u'T', Qt::CaseInsensitive)
5802 || isoString.startsWith(u' '))) {
5805 isoString = isoString.sliced(1);
5808 if (isoString.endsWith(u'Z', Qt::CaseInsensitive)) {
5809 zone = QTimeZone::UTC;
5814 int signIndex = isoString.size() - 1;
5815 Q_ASSERT(signIndex >= 0);
5818 QChar character(isoString[signIndex]);
5819 found = character == u'+' || character == u'-';
5820 }
while (!found && --signIndex >= 0);
5824 int offset = fromOffsetString(isoString.sliced(signIndex), &ok);
5827 isoString = isoString.first(signIndex);
5828 zone = QTimeZone::fromSecondsAheadOfUtc(offset);
5834 bool isMidnight24 =
false;
5835 QTime time = fromIsoTimeString(isoString, format, &isMidnight24);
5836 if (!time.isValid())
5839 return date.addDays(1).startOfDay(zone);
5840 return QDateTime(date, time, zone);
5842 case Qt::TextDate: {
5843 QVarLengthArray<QStringView, 6> parts;
5845 auto tokens = string.tokenize(u' ', Qt::SkipEmptyParts);
5846 auto it = tokens.begin();
5847 for (
int i = 0; i < 6 && it != tokens.end(); ++i, ++it)
5848 parts.emplace_back(*it);
5852 if (parts.size() < 5 || it != tokens.end())
5859 if (parts.at(3).contains(u':'))
5861 else if (parts.at(4).contains(u':'))
5867 int day = parts.at(2).toInt(&ok);
5868 int year = ok ? parts.at(yearPart).toInt(&ok) : 0;
5869 int month = fromShortMonthName(parts.at(1));
5870 if (!ok || year == 0 || day == 0 || month < 1)
5873 const QDate date(year, month, day);
5874 if (!date.isValid())
5877 const QTime time = fromIsoTimeString(parts.at(timePart), format,
nullptr);
5878 if (!time.isValid())
5881 if (parts.size() == 5)
5882 return QDateTime(date, time);
5884 QStringView tz = parts.at(5);
5885 if (tz.startsWith(
"UTC"_L1)
5887 || tz.startsWith(
"GMT"_L1, Qt::CaseInsensitive)) {
5890 return QDateTime(date, time, QTimeZone::UTC);
5892 int offset = fromOffsetString(tz, &ok);
5893 return ok ? QDateTime(date, time, QTimeZone::fromSecondsAheadOfUtc(offset))
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5987
5988
5989
5990
5993
5994
5995
5996QDateTime QDateTime::fromString(
const QString &string, QStringView format,
int baseYear,
5999#if QT_CONFIG(datetimeparser)
6002 QDateTimeParser dt(QMetaType::QDateTime, QDateTimeParser::FromString, cal);
6003 dt.setDefaultLocale(QLocale::c());
6004 if (dt.parseFormat(format) && (dt.fromString(string, &datetime, baseYear)
6005 || !datetime.isValid())) {
6018
6019
6020
6021
6024
6025
6026
6027
6030
6031
6032
6033
6036
6037
6038
6039
6040
6041
6044
6045
6046
6047
6048
6049QDateTime QDateTime::fromString(
const QString &string, QStringView format,
int baseYear)
6051 return fromString(string, format, baseYear, QCalendar());
6055
6056
6057
6058
6059
6060
6064
6065
6067#ifndef QT_NO_DATASTREAM
6069
6070
6071
6072
6073
6074
6076QDataStream &operator<<(QDataStream &out, QDate date)
6078 if (out.version() < QDataStream::Qt_5_0)
6079 return out << quint32(date.jd);
6081 return out << date.jd;
6085
6086
6087
6088
6089
6090
6092QDataStream &operator>>(QDataStream &in, QDate &date)
6094 if (in.version() < QDataStream::Qt_5_0) {
6098 date.jd = (jd != 0 ? jd : QDate::nullJd());
6107
6108
6109
6110
6111
6112
6114QDataStream &operator<<(QDataStream &out, QTime time)
6116 if (out.version() >= QDataStream::Qt_4_0) {
6117 return out << quint32(time.mds);
6120 return out << quint32(time.isNull() ? 0 : time.mds);
6125
6126
6127
6128
6129
6130
6132QDataStream &operator>>(QDataStream &in, QTime &time)
6136 if (in.version() >= QDataStream::Qt_4_0) {
6140 time.mds = (ds == 0) ? QTime::NullTime :
int(ds);
6146
6147
6148
6149
6150
6151
6152QDataStream &operator<<(QDataStream &out,
const QDateTime &dateTime)
6154 std::pair<QDate, QTime> dateAndTime;
6157 if (out.version() >= QDataStream::Qt_5_2) {
6160 dateAndTime = getDateTime(dateTime.d);
6161 out << dateAndTime << qint8(dateTime.timeSpec());
6162 if (dateTime.timeSpec() == Qt::OffsetFromUTC)
6163 out << qint32(dateTime.offsetFromUtc());
6164#if QT_CONFIG(timezone)
6165 else if (dateTime.timeSpec() == Qt::TimeZone)
6166 out << dateTime.timeZone();
6169 }
else if (out.version() == QDataStream::Qt_5_0) {
6175 dateAndTime = getDateTime((dateTime.isValid() ? dateTime.toUTC() : dateTime).d);
6176 out << dateAndTime << qint8(dateTime.timeSpec());
6178 }
else if (out.version() >= QDataStream::Qt_4_0) {
6181 dateAndTime = getDateTime(dateTime.d);
6183 switch (dateTime.timeSpec()) {
6185 out << (qint8)QDateTimePrivate::UTC;
6187 case Qt::OffsetFromUTC:
6188 out << (qint8)QDateTimePrivate::OffsetFromUTC;
6191 out << (qint8)QDateTimePrivate::TimeZone;
6194 out << (qint8)QDateTimePrivate::LocalUnknown;
6201 dateAndTime = getDateTime(dateTime.d);
6210
6211
6212
6213
6214
6215
6217QDataStream &operator>>(QDataStream &in, QDateTime &dateTime)
6222 QTimeZone zone(QTimeZone::LocalTime);
6224 if (in.version() >= QDataStream::Qt_5_2) {
6227 in >> dt >> tm >> ts;
6228 switch (
static_cast<Qt::TimeSpec>(ts)) {
6230 zone = QTimeZone::UTC;
6232 case Qt::OffsetFromUTC: {
6235 zone = QTimeZone::fromSecondsAheadOfUtc(offset);
6245 dateTime = QDateTime(dt, tm, zone);
6247 }
else if (in.version() == QDataStream::Qt_5_0) {
6250 in >> dt >> tm >> ts;
6251 dateTime = QDateTime(dt, tm, QTimeZone::UTC);
6252 if (
static_cast<Qt::TimeSpec>(ts) == Qt::LocalTime)
6253 dateTime = dateTime.toTimeZone(zone);
6255 }
else if (in.version() >= QDataStream::Qt_4_0) {
6258 in >> dt >> tm >> ts;
6259 switch (
static_cast<QDateTimePrivate::Spec>(ts)) {
6260 case QDateTimePrivate::OffsetFromUTC:
6261 case QDateTimePrivate::UTC:
6262 zone = QTimeZone::UTC;
6264 case QDateTimePrivate::TimeZone:
6265 case QDateTimePrivate::LocalUnknown:
6266 case QDateTimePrivate::LocalStandard:
6267 case QDateTimePrivate::LocalDST:
6270 dateTime = QDateTime(dt, tm, zone);
6276 dateTime = QDateTime(dt, tm);
6285
6286
6288#if !defined(QT_NO_DEBUG_STREAM) && QT_CONFIG(datestring)
6289QDebug operator<<(QDebug dbg, QDate date)
6291 QDebugStateSaver saver(dbg);
6292 dbg.nospace() <<
"QDate(";
6295 if (
int y = date.year(); y > 0 && y <= 9999)
6296 dbg.nospace() << date.toString(Qt::ISODate);
6298 dbg.nospace() << date.toString(Qt::TextDate);
6300 dbg.nospace() <<
"Invalid";
6301 dbg.nospace() <<
')';
6305QDebug operator<<(QDebug dbg, QTime time)
6307 QDebugStateSaver saver(dbg);
6308 dbg.nospace() <<
"QTime(";
6310 dbg.nospace() << time.toString(u"HH:mm:ss.zzz");
6312 dbg.nospace() <<
"Invalid";
6313 dbg.nospace() <<
')';
6317QDebug operator<<(QDebug dbg,
const QDateTime &date)
6319 QDebugStateSaver saver(dbg);
6320 dbg.nospace() <<
"QDateTime(";
6321 if (date.isValid()) {
6322 const Qt::TimeSpec ts = date.timeSpec();
6323 dbg.noquote() << date.toString(u"yyyy-MM-dd HH:mm:ss.zzz t")
6328 case Qt::OffsetFromUTC:
6329 dbg.space() << date.offsetFromUtc() <<
's';
6332#if QT_CONFIG(timezone)
6333 dbg.space() << date.timeZone().id();
6340 dbg.nospace() <<
"Invalid";
6342 return dbg.nospace() <<
')';
6347
6348
6349
6356 return key.isValid() ? qHash(key.toMSecsSinceEpoch(), seed) : seed;
6360
6361
6362
6365 return qHash(key.toJulianDay(), seed);
6369
6370
6371
6374 return qHash(key.msecsSinceStartOfDay(), seed);
size_t qHash(QTime key, size_t seed) noexcept
\qhashold{QHash}
static QTime msecsToTime(qint64 msecs)
static auto millisToWithinRange(qint64 millis)
static QDateTime toLatest(QDate day, const QTimeZone &zone)
static constexpr QDateTimePrivate::StatusFlags mergeDaylightStatus(QDateTimePrivate::StatusFlags sf, QDateTimePrivate::DaylightStatus status)
static QDate fixedDate(QCalendar::YearMonthDay parts)
static qint64 timeToMSecs(QDate date, QTime time)
static std::pair< QDate, QTime > getDateTime(const QDateTimeData &d)
static constexpr QDateTimePrivate::DaylightStatus extractDaylightStatus(QDateTimePrivate::StatusFlags status)
size_t qHash(const QDateTime &key, size_t seed)
\qhashold{QHash}
static Qt::TimeSpec getSpec(const QDateTimeData &d)
QDateTimePrivate::QDateTimeShortData ShortData
static void reviseTimeZone(QDateTimeData &d, const QTimeZone &zone, QDateTime::TransitionResolution resolve)
static QDateTimePrivate::StatusFlags getStatus(const QDateTimeData &d)
static qint64 getMSecs(const QDateTimeData &d)
static void massageAdjustedDateTime(QDateTimeData &d, QDate date, QTime time, bool forward)
static bool inDateTimeRange(qint64 jd, DaySide side)
QDateTimePrivate::QDateTimeData QDateTimeData
static bool specCanBeSmall(Qt::TimeSpec spec)
static int systemTimeYearMatching(int year)
static constexpr QDateTimePrivate::StatusFlags mergeSpec(QDateTimePrivate::StatusFlags status, Qt::TimeSpec spec)
static QDate msecsToDate(qint64 msecs)
static QString toOffsetString(Qt::DateFormat format, int offset)
size_t qHash(QDate key, size_t seed) noexcept
\qhashold{QHash}
static bool daysAndMillisOverflow(qint64 days, qint64 millisInDay, qint64 *sumMillis)
static QDate fixedDate(QCalendar::YearMonthDay parts, QCalendar cal)
static constexpr QDateTimePrivate::TransitionOptions toTransitionOptions(QDateTime::TransitionResolution res)
static void refreshSimpleDateTime(QDateTimeData &d)
bool areFarEnoughApart(qint64 leftMillis, qint64 rightMillis)
static void setDateTime(QDateTimeData &d, QDate date, QTime time)
static void refreshZonedDateTime(QDateTimeData &d, const QTimeZone &zone, QDateTimePrivate::TransitionOptions resolve)
static bool msecsCanBeSmall(qint64 msecs)
static constexpr Qt::TimeSpec extractSpec(QDateTimePrivate::StatusFlags status)
static bool usesSameOffset(const QDateTimeData &a, const QDateTimeData &b)
static void checkValidDateTime(QDateTimeData &d, QDateTime::TransitionResolution resolve)
Qt::weak_ordering compareThreeWay(const QDateTime &lhs, const QDateTime &rhs)
static QDateTime toEarliest(QDate day, const QTimeZone &zone)
static QDateTimePrivate::ZoneState stateAtMillis(const QTimeZone &zone, qint64 millis, QDateTimePrivate::TransitionOptions resolve)
static bool millisInSystemRange(qint64 millis, qint64 slack=0)
static qint64 msecsToJulianDay(qint64 msecs)