summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/tools/qdatetime.cpp106
-rw-r--r--src/corelib/tools/qdatetime.h1
-rw-r--r--tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp33
3 files changed, 139 insertions, 1 deletions
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index 008e72af1c..db0f7d3a74 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -174,6 +174,7 @@ static void rfcDateImpl(const QString &s, QDate *dd = 0, QTime *dt = 0, int *utf
#endif
static QDateTimePrivate::Spec utcToLocal(QDate &date, QTime &time);
static void utcToOffset(QDate *date, QTime *time, qint32 offset);
+static QDate adjustDate(QDate date);
// Return offset in [+-]HH:MM format
// Qt::ISODate puts : between the hours and minutes, but Qt:TextDate does not
@@ -225,6 +226,68 @@ static int fromOffsetString(const QString &offsetString, bool *valid)
return ((hour * 60) + minute) * 60;
}
+#if !defined(Q_OS_WINCE)
+// Calls the platform variant of mktime for the given date and time,
+// and updates the date, time, spec and abbreviation with the returned values
+// If the date falls outside the 1970 to 2037 range supported by mktime / time_t
+// then null date/time will be returned, you should call adjustDate() first if
+// you need a guaranteed result.
+static time_t qt_mktime(QDate *date, QTime *time, QDateTimePrivate::Spec *spec,
+ QString *abbreviation, bool *ok)
+{
+ if (ok)
+ *ok = false;
+ int yy, mm, dd;
+ date->getDate(&yy, &mm, &dd);
+ tm local;
+ local.tm_sec = time->second();
+ local.tm_min = time->minute();
+ local.tm_hour = time->hour();
+ local.tm_mday = dd;
+ local.tm_mon = mm - 1;
+ local.tm_year = yy - 1900;
+ local.tm_wday = 0;
+ local.tm_yday = 0;
+ local.tm_isdst = -1;
+#if defined(Q_OS_WIN)
+ _tzset();
+#else
+ tzset();
+#endif // Q_OS_WIN
+ const time_t secsSinceEpoch = mktime(&local);
+ if (secsSinceEpoch != (uint)-1) {
+ *date = QDate(local.tm_year + 1900, local.tm_mon + 1, local.tm_mday);
+ *time = QTime(local.tm_hour, local.tm_min, local.tm_sec, time->msec());
+ if (local.tm_isdst == 1) {
+ if (spec)
+ *spec = QDateTimePrivate::LocalDST;
+ if (abbreviation)
+ *abbreviation = QString::fromLocal8Bit(tzname[1]);
+ } else if (local.tm_isdst == 0) {
+ if (spec)
+ *spec = QDateTimePrivate::LocalStandard;
+ if (abbreviation)
+ *abbreviation = QString::fromLocal8Bit(tzname[0]);
+ } else {
+ if (spec)
+ *spec = QDateTimePrivate::LocalUnknown;
+ if (abbreviation)
+ *abbreviation = QString::fromLocal8Bit(tzname[0]);
+ }
+ if (ok)
+ *ok = true;
+ } else {
+ *date = QDate();
+ *time = QTime();
+ if (spec)
+ *spec = QDateTimePrivate::LocalUnknown;
+ if (abbreviation)
+ *abbreviation = QString();
+ }
+ return secsSinceEpoch;
+}
+#endif // !Q_OS_WINCE
+
/*****************************************************************************
QDate member functions
*****************************************************************************/
@@ -2457,6 +2520,49 @@ int QDateTime::offsetFromUtc() const
}
/*!
+ \since 5.2
+
+ Returns the Time Zone Abbreviation for the datetime.
+
+ If the timeSpec() is Qt::UTC this will be "UTC".
+
+ If the timeSpec() is Qt::OffsetFromUTC this will be in the format
+ "UTC[+-]00:00".
+
+ If the timeSpec() is Qt::LocalTime then the host system is queried for the
+ correct abbreviation.
+
+ Note that abbreviations may or may not be localized.
+
+ Note too that the abbreviation is not guaranteed to be a unique value,
+ i.e. different time zones may have the same abbreviation.
+
+ \sa timeSpec()
+*/
+
+QString QDateTime::timeZoneAbbreviation() const
+{
+ switch (d->spec) {
+ case QDateTimePrivate::UTC:
+ return QStringLiteral("UTC");
+ case QDateTimePrivate::OffsetFromUTC:
+ return QLatin1String("UTC") + toOffsetString(Qt::ISODate, d->m_offsetFromUtc);
+ default: { // Any Qt::LocalTime
+#if defined(Q_OS_WINCE)
+ // TODO Stub to enable compilation on WinCE
+ return QString();
+#else
+ QDate dt = adjustDate(d->date);
+ QTime tm = d->time;
+ QString abbrev;
+ qt_mktime(&dt, &tm, 0, &abbrev, 0);
+ return abbrev;
+#endif // !Q_OS_WINCE
+ }
+ }
+}
+
+/*!
Sets the date part of this datetime to \a date.
If no time is set, it is set to midnight.
diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h
index 3c8b1a9920..25f5b74eb2 100644
--- a/src/corelib/tools/qdatetime.h
+++ b/src/corelib/tools/qdatetime.h
@@ -219,6 +219,7 @@ public:
QTime time() const;
Qt::TimeSpec timeSpec() const;
int offsetFromUtc() const;
+ QString timeZoneAbbreviation() const;
qint64 toMSecsSinceEpoch() const;
// ### Qt 6: use quint64 instead of uint
diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp
index 5576d3d8a4..917e931988 100644
--- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp
+++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp
@@ -133,6 +133,8 @@ private slots:
void setOffsetFromUtc();
void toOffsetFromUtc();
+ void timeZoneAbbreviation();
+
void getDate();
void fewDigitsInYear() const;
@@ -592,7 +594,7 @@ void tst_QDateTime::fromMSecsSinceEpoch()
QCOMPARE(dtUtc.time(), utc.time());
QCOMPARE(dtOffset, utc);
- QCOMPARE(dtOffset.utcOffset(), 60*60);
+ QCOMPARE(dtOffset.offsetFromUtc(), 60*60);
QCOMPARE(dtOffset.time(), utc.time().addMSecs(60*60*1000));
if (europeanTimeZone) {
@@ -2221,6 +2223,35 @@ void tst_QDateTime::toOffsetFromUtc()
QCOMPARE(dt2.time(), QTime(0, 0, 0));
}
+void tst_QDateTime::timeZoneAbbreviation()
+{
+ QDateTime dt1(QDate(2013, 1, 1), QTime(1, 0, 0), Qt::OffsetFromUTC, 60 * 60);
+ QCOMPARE(dt1.timeZoneAbbreviation(), QString("UTC+01:00"));
+ QDateTime dt2(QDate(2013, 1, 1), QTime(1, 0, 0), Qt::OffsetFromUTC, -60 * 60);
+ QCOMPARE(dt2.timeZoneAbbreviation(), QString("UTC-01:00"));
+
+ QDateTime dt3(QDate(2013, 1, 1), QTime(0, 0, 0), Qt::UTC);
+ QCOMPARE(dt3.timeZoneAbbreviation(), QString("UTC"));
+
+ // LocalTime should vary
+ if (europeanTimeZone) {
+ // Time definitely in Standard Time
+ QDateTime dt4(QDate(2013, 1, 1), QTime(0, 0, 0), Qt::LocalTime);
+#ifdef Q_OS_WIN
+ QEXPECT_FAIL("", "Windows only returns long name (QTBUG-32759)", Continue);
+#endif // Q_OS_WIN
+ QCOMPARE(dt4.timeZoneAbbreviation(), QString("CET"));
+ // Time definitely in Daylight Time
+ QDateTime dt5(QDate(2013, 6, 1), QTime(0, 0, 0), Qt::LocalTime);
+#ifdef Q_OS_WIN
+ QEXPECT_FAIL("", "Windows only returns long name (QTBUG-32759)", Continue);
+#endif // Q_OS_WIN
+ QCOMPARE(dt5.timeZoneAbbreviation(), QString("CEST"));
+ } else {
+ QSKIP("You must test using Central European (CET/CEST) time zone, e.g. TZ=Europe/Oslo");
+ }
+}
+
void tst_QDateTime::getDate()
{
{