File indexing completed on 2024-05-05 04:42:43

0001 /*
0002     SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "mergeutil_p.h"
0008 
0009 #include <QDateTime>
0010 #include <QDebug>
0011 #include <QString>
0012 #include <QTimeZone>
0013 #include <QUrl>
0014 
0015 using namespace KPublicTransport;
0016 
0017 static QDateTime applyTimeZone(QDateTime dt, const QDateTime &refDt)
0018 {
0019     if (dt.timeSpec() != Qt::LocalTime) {
0020         return dt;
0021     }
0022 
0023     if (refDt.timeSpec() == Qt::TimeZone) {
0024         dt.setTimeZone(refDt.timeZone());
0025     } else if (refDt.timeSpec() == Qt::OffsetFromUTC) {
0026         dt.setTimeZone(QTimeZone::fromSecondsAheadOfUtc(refDt.offsetFromUtc()));
0027     }
0028 
0029     return dt;
0030 }
0031 
0032 int MergeUtil::distance(const QDateTime& lhs, const QDateTime& rhs)
0033 {
0034     const auto ldt = applyTimeZone(lhs, rhs);
0035     const auto rdt = applyTimeZone(rhs, lhs);
0036     return std::abs(ldt.secsTo(rdt));
0037 }
0038 
0039 bool MergeUtil::isBefore(const QDateTime& lhs, const QDateTime& rhs)
0040 {
0041     const auto ldt = applyTimeZone(lhs, rhs);
0042     const auto rdt = applyTimeZone(rhs, lhs);
0043     return ldt < rdt;
0044 }
0045 
0046 QDateTime MergeUtil::mergeDateTimeEqual(const QDateTime &lhs, const QDateTime &rhs)
0047 {
0048     // anything is better than invalid, timezone is best
0049     if (!rhs.isValid() || lhs.timeSpec() == Qt::TimeZone) {
0050         return lhs;
0051     }
0052     if (!lhs.isValid() || rhs.timeSpec() == Qt::TimeZone) {
0053         return rhs;
0054     }
0055 
0056     // UTC offset it better than local time
0057     if (lhs.timeSpec() == Qt::OffsetFromUTC || rhs.timeSpec() == Qt::LocalTime) {
0058         return lhs;
0059     }
0060     return rhs;
0061 }
0062 
0063 QDateTime MergeUtil::mergeDateTimeMax(const QDateTime &lhs, const QDateTime &rhs)
0064 {
0065     // if only one side is valid, prefer that one
0066     if (!lhs.isValid()) {
0067         return rhs;
0068     }
0069     if (!rhs.isValid()) {
0070         return lhs;
0071     }
0072 
0073     auto dt = isBefore(lhs, rhs) ? rhs : lhs;
0074     if (dt.timeSpec() == Qt::TimeZone) {
0075         return dt;
0076     }
0077 
0078     // recover timezone of we can
0079     if (lhs.timeSpec() == Qt::TimeZone) {
0080         dt.setTimeZone(lhs.timeZone());
0081         return dt;
0082     } else if (rhs.timeSpec() == Qt::TimeZone) {
0083         dt.setTimeZone(rhs.timeZone());
0084         return dt;
0085     }
0086 
0087     // recover UTC offset if we can
0088     if (dt.timeSpec() == Qt::OffsetFromUTC) {
0089         return dt;
0090     } else if (lhs.timeSpec() == Qt::OffsetFromUTC) {
0091         dt.setTimeZone(QTimeZone::fromSecondsAheadOfUtc(lhs.offsetFromUtc()));
0092     } else if (rhs.timeSpec() == Qt::OffsetFromUTC) {
0093         dt.setTimeZone(QTimeZone::fromSecondsAheadOfUtc(rhs.offsetFromUtc()));
0094     }
0095 
0096     return dt;
0097 }
0098 
0099 QString MergeUtil::mergeString(const QString &lhs, const QString &rhs)
0100 {
0101     // ### this is deterministic, but not necessarily ideal
0102     // we could prefer mixed case over all caps, unicode over transliterated, etc
0103     if (lhs.size() == rhs.size()) {
0104         return lhs < rhs ? lhs : rhs;
0105     }
0106     return lhs.size() < rhs.size() ? rhs : lhs;
0107 }