[nightcolor] Use local time in Automatic and Location mode
Summary: Currently Night Color doesn't handle time zones very well. For example, if the user's time zone is UTC-8, then computed timings of sunrise and sunset (in UTC) will be a bit gibberish as sunset occurs before sunrise rather than vice versa. This change switches relevant parts of Night Color to local time in order to fix expectations about the order of morning and evening in updateSunTimings() method as well to simplify the code a bit (dealing with UTC and local time can be painful sometimes). CCBUG: 412211 Reviewers: #kwin, romangg Reviewed By: #kwin, romangg Subscribers: romangg, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D24153
This commit is contained in:
parent
3e7d9cd1ab
commit
c265c7f2c6
4 changed files with 53 additions and 50 deletions
|
@ -371,13 +371,7 @@ void Manager::resetSlowUpdateStartTimer()
|
|||
connect(m_slowUpdateStartTimer, &QTimer::timeout, this, &Manager::resetSlowUpdateStartTimer);
|
||||
|
||||
updateSunTimings(false);
|
||||
int diff;
|
||||
if (m_mode == NightColorMode::Timings) {
|
||||
// Timings mode is in local time
|
||||
diff = QDateTime::currentDateTime().msecsTo(m_next.first);
|
||||
} else {
|
||||
diff = QDateTime::currentDateTimeUtc().msecsTo(m_next.first);
|
||||
}
|
||||
const int diff = QDateTime::currentDateTime().msecsTo(m_next.first);
|
||||
if (diff <= 0) {
|
||||
qCCritical(KWIN_COLORCORRECTION) << "Error in time calculation. Deactivating Night Color.";
|
||||
return;
|
||||
|
@ -393,7 +387,7 @@ void Manager::resetSlowUpdateTimer()
|
|||
delete m_slowUpdateTimer;
|
||||
m_slowUpdateTimer = nullptr;
|
||||
|
||||
QDateTime now = QDateTime::currentDateTimeUtc();
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
bool isDay = daylight();
|
||||
int targetTemp = isDay ? m_dayTargetTemp : m_nightTargetTemp;
|
||||
|
||||
|
@ -443,21 +437,18 @@ void Manager::slowUpdate(int targetTemp)
|
|||
|
||||
void Manager::updateSunTimings(bool force)
|
||||
{
|
||||
QDateTime todayNow = QDateTime::currentDateTimeUtc();
|
||||
QDateTime todayNow = QDateTime::currentDateTime();
|
||||
|
||||
if (m_mode == NightColorMode::Timings) {
|
||||
|
||||
QDateTime todayNowLocal = QDateTime::currentDateTime();
|
||||
|
||||
QDateTime morB = QDateTime(todayNowLocal.date(), m_morning);
|
||||
QDateTime morB = QDateTime(todayNow.date(), m_morning);
|
||||
QDateTime morE = morB.addSecs(m_trTime * 60);
|
||||
QDateTime eveB = QDateTime(todayNowLocal.date(), m_evening);
|
||||
QDateTime eveB = QDateTime(todayNow.date(), m_evening);
|
||||
QDateTime eveE = eveB.addSecs(m_trTime * 60);
|
||||
|
||||
if (morB <= todayNowLocal && todayNowLocal < eveB) {
|
||||
if (morB <= todayNow && todayNow < eveB) {
|
||||
m_next = DateTimes(eveB, eveE);
|
||||
m_prev = DateTimes(morB, morE);
|
||||
} else if (todayNowLocal < morB) {
|
||||
} else if (todayNow < morB) {
|
||||
m_next = DateTimes(morB, morE);
|
||||
m_prev = DateTimes(eveB.addDays(-1), eveE.addDays(-1));
|
||||
} else {
|
||||
|
@ -481,62 +472,63 @@ void Manager::updateSunTimings(bool force)
|
|||
if (daylight()) {
|
||||
// next is morning
|
||||
m_prev = m_next;
|
||||
m_next = getSunTimings(todayNow.date().addDays(1), lat, lng, true);
|
||||
m_next = getSunTimings(todayNow.addDays(1), lat, lng, true);
|
||||
} else {
|
||||
// next is evening
|
||||
m_prev = m_next;
|
||||
m_next = getSunTimings(todayNow.date(), lat, lng, false);
|
||||
m_next = getSunTimings(todayNow, lat, lng, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (force || !checkAutomaticSunTimings()) {
|
||||
// in case this fails, reset them
|
||||
DateTimes morning = getSunTimings(todayNow.date(), lat, lng, true);
|
||||
DateTimes morning = getSunTimings(todayNow, lat, lng, true);
|
||||
if (todayNow < morning.first) {
|
||||
m_prev = getSunTimings(todayNow.date().addDays(-1), lat, lng, false);
|
||||
m_prev = getSunTimings(todayNow.addDays(-1), lat, lng, false);
|
||||
m_next = morning;
|
||||
} else {
|
||||
DateTimes evening = getSunTimings(todayNow.date(), lat, lng, false);
|
||||
DateTimes evening = getSunTimings(todayNow, lat, lng, false);
|
||||
if (todayNow < evening.first) {
|
||||
m_prev = morning;
|
||||
m_next = evening;
|
||||
} else {
|
||||
m_prev = evening;
|
||||
m_next = getSunTimings(todayNow.date().addDays(1), lat, lng, true);
|
||||
m_next = getSunTimings(todayNow.addDays(1), lat, lng, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DateTimes Manager::getSunTimings(QDate date, double latitude, double longitude, bool morning) const
|
||||
DateTimes Manager::getSunTimings(const QDateTime &dateTime, double latitude, double longitude, bool morning) const
|
||||
{
|
||||
Times times = calculateSunTimings(date, latitude, longitude, morning);
|
||||
DateTimes dateTimes = calculateSunTimings(dateTime, latitude, longitude, morning);
|
||||
// At locations near the poles it is possible, that we can't
|
||||
// calculate some or all sun timings (midnight sun).
|
||||
// In this case try to fallback to sensible default values.
|
||||
bool beginDefined = !times.first.isNull();
|
||||
bool endDefined = !times.second.isNull();
|
||||
bool beginDefined = !dateTimes.first.isNull();
|
||||
bool endDefined = !dateTimes.second.isNull();
|
||||
if (!beginDefined || !endDefined) {
|
||||
if (beginDefined) {
|
||||
times.second = times.first.addMSecs( FALLBACK_SLOW_UPDATE_TIME );
|
||||
dateTimes.second = dateTimes.first.addMSecs( FALLBACK_SLOW_UPDATE_TIME );
|
||||
} else if (endDefined) {
|
||||
times.first = times.second.addMSecs( - FALLBACK_SLOW_UPDATE_TIME);
|
||||
dateTimes.first = dateTimes.second.addMSecs( - FALLBACK_SLOW_UPDATE_TIME );
|
||||
} else {
|
||||
// Just use default values for morning and evening, but the user
|
||||
// will probably deactivate Night Color anyway if he is living
|
||||
// in a region without clear sun rise and set.
|
||||
times.first = morning ? QTime(6,0,0) : QTime(18,0,0);
|
||||
times.second = times.first.addMSecs( FALLBACK_SLOW_UPDATE_TIME );
|
||||
const QTime referenceTime = morning ? QTime(6, 0) : QTime(18, 0);
|
||||
dateTimes.first = QDateTime(dateTime.date(), referenceTime);
|
||||
dateTimes.second = dateTimes.first.addMSecs( FALLBACK_SLOW_UPDATE_TIME );
|
||||
}
|
||||
}
|
||||
return DateTimes(QDateTime(date, times.first, Qt::UTC), QDateTime(date, times.second, Qt::UTC));
|
||||
return dateTimes;
|
||||
}
|
||||
|
||||
bool Manager::checkAutomaticSunTimings() const
|
||||
{
|
||||
if (m_prev.first.isValid() && m_prev.second.isValid() &&
|
||||
m_next.first.isValid() && m_next.second.isValid()) {
|
||||
QDateTime todayNow = QDateTime::currentDateTimeUtc();
|
||||
QDateTime todayNow = QDateTime::currentDateTime();
|
||||
return m_prev.first <= todayNow && todayNow < m_next.first &&
|
||||
m_prev.first.msecsTo(m_next.first) < MSC_DAY * 23./24;
|
||||
}
|
||||
|
@ -558,7 +550,7 @@ int Manager::currentTargetTemp() const
|
|||
return m_nightTargetTemp;
|
||||
}
|
||||
|
||||
QDateTime todayNow = QDateTime::currentDateTimeUtc();
|
||||
QDateTime todayNow = QDateTime::currentDateTime();
|
||||
|
||||
auto f = [this, todayNow](int target1, int target2) {
|
||||
if (todayNow <= m_prev.second) {
|
||||
|
|
|
@ -154,7 +154,7 @@ private:
|
|||
void resetSlowUpdateTimer();
|
||||
|
||||
void updateSunTimings(bool force);
|
||||
DateTimes getSunTimings(QDate date, double latitude, double longitude, bool morning) const;
|
||||
DateTimes getSunTimings(const QDateTime &dateTime, double latitude, double longitude, bool morning) const;
|
||||
bool checkAutomaticSunTimings() const;
|
||||
bool daylight() const;
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "constants.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QTimeZone>
|
||||
#include <QtMath>
|
||||
|
||||
namespace KWin {
|
||||
|
@ -31,7 +32,14 @@ namespace ColorCorrect {
|
|||
#define SUN_RISE_SET -0.833
|
||||
#define SUN_HIGH 2.0
|
||||
|
||||
QPair<QTime, QTime> calculateSunTimings(QDate prompt, double latitude, double longitude, bool morning)
|
||||
static QTime convertToLocalTime(const QDateTime &when, const QTime &utcTime)
|
||||
{
|
||||
const QTimeZone timeZone = QTimeZone::systemTimeZone();
|
||||
const int utcOffset = timeZone.offsetFromUtc(when);
|
||||
return utcTime.addSecs(utcOffset);
|
||||
}
|
||||
|
||||
QPair<QDateTime, QDateTime> calculateSunTimings(const QDateTime &dateTime, double latitude, double longitude, bool morning)
|
||||
{
|
||||
// calculations based on https://aa.quae.nl/en/reken/zonpositie.html
|
||||
// accuracy: +/- 5min
|
||||
|
@ -44,7 +52,8 @@ QPair<QTime, QTime> calculateSunTimings(QDate prompt, double latitude, double lo
|
|||
const double lng = -longitude; // lw
|
||||
|
||||
// times
|
||||
const double juPrompt = prompt.toJulianDay(); // J
|
||||
const QDateTime utcDateTime = dateTime.toUTC();
|
||||
const double juPrompt = utcDateTime.date().toJulianDay(); // J
|
||||
const double ju2000 = 2451545.; // J2000
|
||||
|
||||
// geometry
|
||||
|
@ -141,22 +150,24 @@ QPair<QTime, QTime> calculateSunTimings(QDate prompt, double latitude, double lo
|
|||
begin += 0.5;
|
||||
end += 0.5;
|
||||
|
||||
QTime timeBegin, timeEnd;
|
||||
QDateTime dateTimeBegin;
|
||||
QDateTime dateTimeEnd;
|
||||
|
||||
if (std::isnan(begin)) {
|
||||
timeBegin = QTime();
|
||||
} else {
|
||||
double timePart = begin - (int)begin;
|
||||
timeBegin = QTime::fromMSecsSinceStartOfDay((int)( timePart * MSC_DAY ));
|
||||
}
|
||||
if (std::isnan(end)) {
|
||||
timeEnd = QTime();
|
||||
} else {
|
||||
double timePart = end - (int)end;
|
||||
timeEnd = QTime::fromMSecsSinceStartOfDay((int)( timePart * MSC_DAY ));
|
||||
if (!std::isnan(begin)) {
|
||||
const double dayFraction = begin - int(begin);
|
||||
const QTime utcTime = QTime::fromMSecsSinceStartOfDay(dayFraction * MSC_DAY);
|
||||
const QTime localTime = convertToLocalTime(dateTime, utcTime);
|
||||
dateTimeBegin = QDateTime(dateTime.date(), localTime);
|
||||
}
|
||||
|
||||
return QPair<QTime,QTime> (timeBegin, timeEnd);
|
||||
if (!std::isnan(end)) {
|
||||
const double dayFraction = end - int(end);
|
||||
const QTime utcTime = QTime::fromMSecsSinceStartOfDay(dayFraction * MSC_DAY);
|
||||
const QTime localTime = convertToLocalTime(dateTime, utcTime);
|
||||
dateTimeEnd = QDateTime(dateTime.date(), localTime);
|
||||
}
|
||||
|
||||
return { dateTimeBegin, dateTimeEnd };
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace ColorCorrect
|
|||
* @since 5.12
|
||||
*/
|
||||
|
||||
QPair<QTime, QTime> calculateSunTimings(QDate prompt, double latitude, double longitude, bool morning);
|
||||
QPair<QDateTime, QDateTime> calculateSunTimings(const QDateTime &dateTime, double latitude, double longitude, bool morning);
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue