diff --git a/runners/datetime/datetimerunner.h b/runners/datetime/datetimerunner.h --- a/runners/datetime/datetimerunner.h +++ b/runners/datetime/datetimerunner.h @@ -20,6 +20,7 @@ #define DATETIMERUNNER_H #include +#include #include #include @@ -42,7 +43,7 @@ void match(Plasma::RunnerContext &context) override; private: - QDateTime datetime(const QString &tz, QString &tzName); + QTimeZone timeZone(const QString &tz, QString &tzName); void addMatch(const QString &text, const QString &clipboardText, Plasma::RunnerContext &context, const QString& iconName); }; diff --git a/runners/datetime/datetimerunner.cpp b/runners/datetime/datetimerunner.cpp --- a/runners/datetime/datetimerunner.cpp +++ b/runners/datetime/datetimerunner.cpp @@ -2,6 +2,7 @@ * Copyright (C) 2006 Aaron Seigo * Copyright (C) 2010 Marco Martin * Copyright (C) 2015 Vishesh Handa + * Copyright (C) 2018 James D. Smith * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License version 2 as @@ -37,43 +38,123 @@ addSyntax(Plasma::RunnerSyntax(dateWord, i18n("Displays the current date"))); addSyntax(Plasma::RunnerSyntax(dateWord + QLatin1String( " :q:" ), i18n("Displays the current date in a given timezone"))); addSyntax(Plasma::RunnerSyntax(timeWord, i18n("Displays the current time"))); + addSyntax(Plasma::RunnerSyntax(timeWord + QLatin1String( " 24" ), i18n("Displays the current time, in 24 hour time"))); addSyntax(Plasma::RunnerSyntax(timeWord + QLatin1String( " :q:" ), i18n("Displays the current time in a given timezone"))); + addSyntax(Plasma::RunnerSyntax(timeWord + QLatin1String( " :q:" ) + QLatin1String( " 24" ), i18n("Displays the local time from the given time of the form hh:mm [am/pm] or HH:mm, in 24 hour time"))); + addSyntax(Plasma::RunnerSyntax(timeWord + QLatin1String( " :q:" ) + QLatin1String( " 24" ), i18n("Displays the current time in a given timezone, in 24 hour time"))); + addSyntax(Plasma::RunnerSyntax(timeWord + QLatin1String( " :q:" ), i18n("Displays the local time from the given time of the form hh:mm [am/pm] or HH:mm"))); + addSyntax(Plasma::RunnerSyntax(timeWord + QLatin1String( " :q:" ) + QLatin1String( " :q:" ), i18n("Displays the time in the given timezone converted from the given local time of the form hh:mm [am/pm] or HH:mm"))); + addSyntax(Plasma::RunnerSyntax(timeWord + QLatin1String( " :q:" ) + QLatin1String( " :q:" ), i18n("Displays the given time of the form hh:mm [am/pm] or HH:mm converted from the given timezone to the local time"))); + addSyntax(Plasma::RunnerSyntax(timeWord + QLatin1String( " :q:" ) + QLatin1String( " :q:" ) + QLatin1String( " 24" ), i18n("Displays the time in the given timezone converted from the given local time of the form hh:mm [am/pm] or HH:mm, in 24 hour time"))); + addSyntax(Plasma::RunnerSyntax(timeWord + QLatin1String( " :q:" ) + QLatin1String( " :q:" ) + QLatin1String( " 24" ), i18n("Displays the given time of the form hh:mm [am/pm] or HH:mm converted from the given timezone to the local time, in 24 hour time"))); } DateTimeRunner::~DateTimeRunner() { } void DateTimeRunner::match(Plasma::RunnerContext &context) { - const QString term = context.query(); - if (term.compare(dateWord, Qt::CaseInsensitive) == 0) { - const QString date = QLocale().toString(QDate::currentDate()); - addMatch(i18n("Today's date is %1", date), date, context, QStringLiteral("view-calendar-day")); - } else if (term.startsWith(dateWord + QLatin1Char( ' ' ), Qt::CaseInsensitive)) { - QString tzName; - QString tz = term.right(term.length() - dateWord.length() - 1); - QDateTime dt = datetime(tz, tzName); - if (dt.isValid()) { - const QString date = QLocale().toString(dt.date()); + const QStringList terms = context.query().split(QChar::Space, QString::SkipEmptyParts); + bool is24Hr = terms.contains(QStringLiteral("24")); + bool toLocalTime = QChar(terms.value(1).at(0)).isNumber(); + + QDateTime dt; + QTime t; + QTimeZone tz; + QString tzName; + QString time; + + for (const QString &term : terms) { + if (term.contains(QStringLiteral(":"))) { + time = term; + } else if (term.compare(QStringLiteral("am"), Qt::CaseInsensitive) == 0) { + time += QChar::Space + term; + } else if (term.compare(QStringLiteral("pm"), Qt::CaseInsensitive) == 0) { + time += QChar::Space + term; + } else if (timeZone(term, tzName).isValid()) { + tz = timeZone(term, tzName); + } + } + + // Possible time formats. + QTime hmmapTime = QTime::fromString(time, QStringLiteral("h:mm ap")); + QTime hhmmapTime = QTime::fromString(time, QStringLiteral("hh:mm ap")); + QTime hmmTime = QTime::fromString(time, QStringLiteral("h:mm")); + QTime hhmmTime = QTime::fromString(time, QStringLiteral("hh:mm")); + + if (hmmapTime.isValid()) { + t = hmmapTime; + } else if (hhmmapTime.isValid()) { + t = hhmmapTime; + } else if (hmmTime.isValid()) { + t = hmmTime; + } else if (hhmmTime.isValid()) { + t = hhmmTime; + } + + if ((terms.size() == 1) || ((terms.size() == 2) && is24Hr)) { + dt = QDateTime::currentDateTime(); + } if (toLocalTime && t.isValid()) { + dt = QDateTime(QDateTime::currentDateTime().date(), t, tz).toLocalTime(); + } else if (!toLocalTime && t.isValid() && tz.isValid()) { + dt = QDateTime(QDateTime::currentDateTime().date(), t).toTimeZone(tz); + } else if (!toLocalTime && !t.isValid() && tz.isValid()) { + dt = QDateTime::currentDateTime().toTimeZone(tz); + } + + if (!dt.isValid()) { + return; + } + + const QString date = QLocale().toString(dt.date()); + + if (terms.value(0).compare(dateWord, Qt::CaseInsensitive) == 0) { + if (dt.timeZone() == QDateTime::currentDateTime().timeZone()) { + addMatch(i18n("Today's date: %1", date), date, context, QStringLiteral("view-calendar-day")); + } else { addMatch(QStringLiteral("%1 - %2").arg(tzName, date), date, context, QStringLiteral("view-calendar-day")); } - } else if (term.compare(timeWord, Qt::CaseInsensitive) == 0) { - const QString time = QLocale().toString(QTime::currentTime()); - addMatch(i18n("Current time is %1", time), time, context, QStringLiteral("clock")); - } else if (term.startsWith(timeWord + QLatin1Char( ' ' ), Qt::CaseInsensitive)) { - QString tzName; - QString tz = term.right(term.length() - timeWord.length() - 1); - QDateTime dt = datetime(tz, tzName); - if (dt.isValid()) { - const QString time = QLocale().toString(dt.time(),QLocale::ShortFormat); + } else if (terms.value(0).compare(timeWord, Qt::CaseInsensitive) == 0) { + QString timeFormat24hr = QLocale().timeFormat(); + timeFormat24hr.remove(QStringLiteral("a"), Qt::CaseInsensitive); + timeFormat24hr.remove(QStringLiteral("p"), Qt::CaseInsensitive); + timeFormat24hr = timeFormat24hr.simplified(); + QString time; + + if (dt.timeZone() == QDateTime::currentDateTime().timeZone()) { + if (is24Hr) { + time = QLocale().toString(dt.time(), timeFormat24hr); + } else { + time = QLocale().toString(dt.time()); + } + + addMatch(i18n("Local time: %1", time), time, context, QStringLiteral("clock")); + } else { + if (is24Hr) { + timeFormat24hr.remove(QStringLiteral("t")); + timeFormat24hr = timeFormat24hr.simplified(); + + time = QLocale().toString(dt.time(), timeFormat24hr); + } else { + time = QLocale().toString(dt.time(), QLocale::ShortFormat); + } + addMatch(QStringLiteral("%1 - %2").arg(tzName, time), time, context, QStringLiteral("clock")); + + if (dt.date() != QDateTime::currentDateTime().date()) { + addMatch(QStringLiteral("%1 - %2").arg(tzName, date), date, context, QStringLiteral("view-calendar-day")); + } } } } -QDateTime DateTimeRunner::datetime(const QString &tz, QString &tzName) +QTimeZone DateTimeRunner::timeZone(const QString &tz, QString &tzName) { + if (tz.isEmpty()) { + return QTimeZone(); + } + // // KTimeZone gives us the actual timezone names such as "Asia/Kolkatta" and does // not give us country info. QTimeZone does not give us the actual timezone name @@ -86,22 +167,22 @@ const QString zoneName = QString::fromUtf8(zoneId); if (zoneName.startsWith(tz, Qt::CaseInsensitive)) { tzName = zoneName; - return QDateTime::currentDateTimeUtc().toTimeZone(timeZone); + return timeZone; } const QString country = QLocale::countryToString(timeZone.country()); if (country.startsWith(tz, Qt::CaseInsensitive)) { tzName = country; - return QDateTime::currentDateTimeUtc().toTimeZone(timeZone); + return timeZone; } // FIXME: This only includes the current abbreviation and not old abbreviation or // other possible names. // Eg - depending on the current date, only CET or CEST will work const QString abbr = timeZone.abbreviation(QDateTime::currentDateTime()); if (abbr.startsWith(tz, Qt::CaseInsensitive)) { tzName = abbr; - return QDateTime::currentDateTimeUtc().toTimeZone(timeZone); + return timeZone; } } @@ -111,11 +192,11 @@ const QString zoneName = QString::fromUtf8(zoneId); if (zoneName.contains(tz, Qt::CaseInsensitive)) { tzName = zoneName; - return QDateTime::currentDateTimeUtc().toTimeZone(timeZone); + return timeZone; } } - return QDateTime(); + return QTimeZone(); } void DateTimeRunner::addMatch(const QString &text, const QString &clipboardText,