summaryrefslogtreecommitdiffstats
path: root/src/corelib/time
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/time')
-rw-r--r--src/corelib/time/qdatetime.cpp46
-rw-r--r--src/corelib/time/qdatetimeparser.cpp13
-rw-r--r--src/corelib/time/qtimezoneprivate_android.cpp15
3 files changed, 49 insertions, 25 deletions
diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp
index c30fd046a4..c1952f9bf5 100644
--- a/src/corelib/time/qdatetime.cpp
+++ b/src/corelib/time/qdatetime.cpp
@@ -90,6 +90,7 @@ enum {
MSECS_PER_HOUR = 3600000,
SECS_PER_MIN = 60,
MSECS_PER_MIN = 60000,
+ MSECS_PER_SEC = 1000,
TIME_T_MAX = 2145916799, // int maximum 2037-12-31T23:59:59 UTC
JULIAN_DAY_FOR_EPOCH = 2440588 // result of julianDayFromDate(1970, 1, 1)
};
@@ -4532,7 +4533,7 @@ QString QDateTime::toString(const QString &format, QCalendar cal) const
#endif // datestring
-static inline void massageAdjustedDateTime(const QDateTimeData &d, QDate *date, QTime *time)
+static inline void massageAdjustedDateTime(QDateTimeData &d, QDate *date, QTime *time)
{
/*
If we have just adjusted to a day with a DST transition, our given time
@@ -4547,16 +4548,44 @@ static inline void massageAdjustedDateTime(const QDateTimeData &d, QDate *date,
answers do then differ only in DST-ness.)
*/
auto spec = getSpec(d);
+ if (spec == Qt::OffsetFromUTC || spec == Qt::UTC) {
+ setDateTime(d, *date, *time);
+ checkValidDateTime(d);
+ return;
+ }
+ auto dst = extractDaylightStatus(getStatus(d));
+ qint64 utc = 0;
+ qint64 local = timeToMSecs(*date, *time);
if (spec == Qt::LocalTime) {
- QDateTimePrivate::DaylightStatus status = QDateTimePrivate::UnknownDaylightTime;
- localMSecsToEpochMSecs(timeToMSecs(*date, *time), &status, date, time);
+ utc = localMSecsToEpochMSecs(local, &dst, date, time);
#if QT_CONFIG(timezone)
} else if (spec == Qt::TimeZone && d.d->m_timeZone.isValid()) {
- QDateTimePrivate::zoneMSecsToEpochMSecs(timeToMSecs(*date, *time),
- d.d->m_timeZone,
- QDateTimePrivate::UnknownDaylightTime,
- date, time);
+ utc = QDateTimePrivate::zoneMSecsToEpochMSecs(local, d.d->m_timeZone, dst, date, time);
+ // update dst, as it's passed to zoneMSecsToEpochMSecs() by value
+ dst = d.d->m_timeZone.isDaylightTime(QDateTime::fromMSecsSinceEpoch(utc))
+ ? QDateTimePrivate::DaylightTime : QDateTimePrivate::StandardTime;
#endif // timezone
+ } else {
+ dst = QDateTimePrivate::UnknownDaylightTime;
+ }
+
+ setDateTime(d, *date, *time);
+
+ auto status = getStatus(d); // Updated by setDateTime()
+ const bool ok = (dst != QDateTimePrivate::UnknownDaylightTime
+ && (status & QDateTimePrivate::ValidDate)
+ && (status & QDateTimePrivate::ValidTime));
+ if (ok)
+ status = mergeDaylightStatus(status | QDateTimePrivate::ValidDateTime, dst);
+ else
+ status &= ~QDateTimePrivate::ValidDateTime;
+
+ if (status & QDateTimePrivate::ShortData) {
+ d.data.status = status;
+ } else {
+ d->m_status = status;
+ if (ok)
+ d->m_offsetFromUtc = (local - utc) / MSECS_PER_SEC;
}
}
@@ -4582,7 +4611,6 @@ QDateTime QDateTime::addDays(qint64 ndays) const
QTime &time = p.second;
date = date.addDays(ndays);
massageAdjustedDateTime(dt.d, &date, &time);
- setDateTime(dt.d, date, time);
return dt;
}
@@ -4608,7 +4636,6 @@ QDateTime QDateTime::addMonths(int nmonths) const
QTime &time = p.second;
date = date.addMonths(nmonths);
massageAdjustedDateTime(dt.d, &date, &time);
- setDateTime(dt.d, date, time);
return dt;
}
@@ -4634,7 +4661,6 @@ QDateTime QDateTime::addYears(int nyears) const
QTime &time = p.second;
date = date.addYears(nyears);
massageAdjustedDateTime(dt.d, &date, &time);
- setDateTime(dt.d, date, time);
return dt;
}
diff --git a/src/corelib/time/qdatetimeparser.cpp b/src/corelib/time/qdatetimeparser.cpp
index c5e0493de5..ce28c6d034 100644
--- a/src/corelib/time/qdatetimeparser.cpp
+++ b/src/corelib/time/qdatetimeparser.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -761,6 +761,11 @@ QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionIndex,
const int sectionmaxsize = sectionMaxSize(sectionIndex);
QStringRef sectionTextRef = text->midRef(offset, sectionmaxsize);
+ // If the fields we've read thus far imply a time in a spring-forward,
+ // coerce to a nearby valid time:
+ const QDateTime defaultValue = currentValue.isValid() ? currentValue
+ : QDateTime::fromMSecsSinceEpoch(currentValue.toMSecsSinceEpoch());
+
QDTPDEBUG << "sectionValue for" << sn.name()
<< "with text" << *text << "and (at" << offset
<< ") st:" << sectionTextRef;
@@ -793,7 +798,7 @@ QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionIndex,
text->replace(offset, used, sectiontext.constData(), used);
break; }
case TimeZoneSection:
- result = findTimeZone(sectionTextRef, currentValue,
+ result = findTimeZone(sectionTextRef, defaultValue,
absoluteMax(sectionIndex),
absoluteMin(sectionIndex));
break;
@@ -805,7 +810,7 @@ QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionIndex,
int num = 0, used = 0;
if (sn.type == MonthSection) {
const QDate minDate = getMinimum().date();
- const int year = currentValue.date().year(calendar);
+ const int year = defaultValue.date().year(calendar);
const int min = (year == minDate.year(calendar)) ? minDate.month(calendar) : 1;
num = findMonth(sectiontext.toLower(), min, sectionIndex, year, &sectiontext, &used);
} else {
@@ -887,7 +892,7 @@ QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionIndex,
else
QDTPDEBUG << "invalid because" << last << "is less than absoluteMin" << absMin;
} else if (unfilled && (fi & (FixedWidth|Numeric)) == (FixedWidth|Numeric)) {
- if (skipToNextSection(sectionIndex, currentValue, digitsStr)) {
+ if (skipToNextSection(sectionIndex, defaultValue, digitsStr)) {
const int missingZeroes = sectionmaxsize - digitsStr.size();
result = ParsedSection(Acceptable, last, sectionmaxsize, missingZeroes);
text->insert(offset, QString(missingZeroes, QLatin1Char('0')));
diff --git a/src/corelib/time/qtimezoneprivate_android.cpp b/src/corelib/time/qtimezoneprivate_android.cpp
index da82832455..3609c65d55 100644
--- a/src/corelib/time/qtimezoneprivate_android.cpp
+++ b/src/corelib/time/qtimezoneprivate_android.cpp
@@ -86,17 +86,10 @@ QAndroidTimeZonePrivate::~QAndroidTimeZonePrivate()
static QJNIObjectPrivate getDisplayName(QJNIObjectPrivate zone, jint style, jboolean dst,
const QLocale &locale)
{
- QJNIObjectPrivate jlanguage
- = QJNIObjectPrivate::fromString(QLocale::languageToString(locale.language()));
- QJNIObjectPrivate jcountry
- = QJNIObjectPrivate::fromString(QLocale::countryToString(locale.country()));
- QJNIObjectPrivate
- jvariant = QJNIObjectPrivate::fromString(QLocale::scriptToString(locale.script()));
- QJNIObjectPrivate jlocale("java.util.Locale",
- "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
- static_cast<jstring>(jlanguage.object()),
- static_cast<jstring>(jcountry.object()),
- static_cast<jstring>(jvariant.object()));
+ QJNIObjectPrivate jbcpTag = QJNIObjectPrivate::fromString(locale.bcp47Name());
+ QJNIObjectPrivate jlocale = QJNIObjectPrivate::callStaticObjectMethod(
+ "java/util/Locale", "forLanguageTag", "(Ljava/lang/String;)Ljava/util/Locale;",
+ static_cast<jstring>(jbcpTag.object()));
return zone.callObjectMethod("getDisplayName",
"(ZILjava/util/Locale;)Ljava/lang/String;",