Commit ee07daeb authored by Volker Krause's avatar Volker Krause
Browse files

Deal with timespec UTC and timezone UTC being two different things

Semantically those are of course exactly the same, but in terms of
comparing QDateTime values one has to handle both cases explicitly.

This fixes times with UTC timezone not being converted to the local
timezone if known. We often get such values from ical sources.
parent 3c970ee7
......@@ -7,6 +7,7 @@
#pragma once
#include <QDateTime>
#include <QTimeZone>
namespace KItinerary {
......@@ -52,7 +53,10 @@ template <> inline bool equals<QVariant>(const QVariant &lhs, const QVariant &rh
// we however want to know if two instances contain exactly the same information
template <> inline bool equals<QDateTime>(const QDateTime &lhs, const QDateTime &rhs)
{
return lhs.timeSpec() == rhs.timeSpec() && lhs == rhs;
if (lhs.timeSpec() != rhs.timeSpec() || lhs != rhs) {
return false;
}
return lhs.timeSpec() == Qt::TimeZone ? lhs.timeZone() == rhs.timeZone() : true;
}
// QString::operator== ignores null vs empty
......
......@@ -326,28 +326,7 @@ QDateTime ExtractorPostprocessorPrivate::processTrainTripTime(QDateTime dt, QDat
if (dt.date().year() <= 1970 && departureDay.isValid()) { // we just have the time, but not the day
dt.setDate(departureDay);
}
if (dt.timeSpec() == Qt::TimeZone) {
return dt;
}
const auto tz = KnowledgeDb::timezoneForLocation(station.geo().latitude(), station.geo().longitude(), station.address().addressCountry(), station.address().addressRegion());
if (!tz.isValid()) {
return dt;
}
// prefer our timezone over externally provided UTC offset, if they match
if (dt.timeSpec() == Qt::OffsetFromUTC && tz.offsetFromUtc(dt) != dt.offsetFromUtc()) {
return dt;
}
if (dt.timeSpec() == Qt::OffsetFromUTC || dt.timeSpec() == Qt::LocalTime) {
dt.setTimeSpec(Qt::TimeZone);
dt.setTimeZone(tz);
} else if (dt.timeSpec() == Qt::UTC) {
dt = dt.toTimeZone(tz);
}
return dt;
return processTimeForLocation(dt, station);
}
BusReservation ExtractorPostprocessorPrivate::processBusReservation(BusReservation res) const
......@@ -637,7 +616,7 @@ QVariantList ExtractorPostprocessorPrivate::processActions(QVariantList actions)
template <typename T>
QDateTime ExtractorPostprocessorPrivate::processTimeForLocation(QDateTime dt, const T &place) const
{
if (!dt.isValid() || dt.timeSpec() == Qt::TimeZone) {
if (!dt.isValid() || (dt.timeSpec() == Qt::TimeZone && dt.timeZone() != QTimeZone::utc())) {
return dt;
}
......@@ -655,7 +634,7 @@ QDateTime ExtractorPostprocessorPrivate::processTimeForLocation(QDateTime dt, co
if (dt.timeSpec() == Qt::OffsetFromUTC || dt.timeSpec() == Qt::LocalTime) {
dt.setTimeSpec(Qt::TimeZone);
dt.setTimeZone(tz);
} else if (dt.timeSpec() == Qt::UTC) {
} else if (dt.timeSpec() == Qt::UTC || (dt.timeSpec() == Qt::TimeZone && dt.timeZone() == QTimeZone::utc())) {
dt = dt.toTimeZone(tz);
}
return dt;
......
......@@ -29,6 +29,7 @@
#include <QDebug>
#include <QMetaObject>
#include <QMetaProperty>
#include <QTimeZone>
#include <QVariant>
#include <cmath>
......@@ -505,6 +506,10 @@ static Airline mergeValue(const Airline &lhs, const Airline &rhs)
static QDateTime mergeValue(const QDateTime &lhs, const QDateTime &rhs)
{
// if both sides have a timezone, prefer non-UTC
if (lhs.isValid() && lhs.timeSpec() == Qt::TimeZone && rhs.isValid() && rhs.timeSpec() == Qt::TimeZone) {
return rhs.timeZone() == QTimeZone::utc() ? lhs : rhs;
}
// prefer value with timezone
return lhs.isValid() && lhs.timeSpec() == Qt::TimeZone && rhs.timeSpec() != Qt::TimeZone ? lhs : rhs;
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment