KPublicTransport

mergeutil.cpp
1/*
2 SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "mergeutil_p.h"
8
9#include <QDateTime>
10#include <QDebug>
11#include <QString>
12#include <QTimeZone>
13#include <QUrl>
14
15using namespace KPublicTransport;
16
17static QDateTime applyTimeZone(QDateTime dt, const QDateTime &refDt)
18{
19 if (dt.timeSpec() != Qt::LocalTime) {
20 return dt;
21 }
22
23 if (refDt.timeSpec() == Qt::TimeZone) {
24 dt.setTimeZone(refDt.timeZone());
25 } else if (refDt.timeSpec() == Qt::OffsetFromUTC) {
27 }
28
29 return dt;
30}
31
32int MergeUtil::distance(const QDateTime& lhs, const QDateTime& rhs)
33{
34 const auto ldt = applyTimeZone(lhs, rhs);
35 const auto rdt = applyTimeZone(rhs, lhs);
36 return std::abs(ldt.secsTo(rdt));
37}
38
39bool MergeUtil::isBefore(const QDateTime& lhs, const QDateTime& rhs)
40{
41 const auto ldt = applyTimeZone(lhs, rhs);
42 const auto rdt = applyTimeZone(rhs, lhs);
43 return ldt < rdt;
44}
45
46QDateTime MergeUtil::mergeDateTimeEqual(const QDateTime &lhs, const QDateTime &rhs)
47{
48 // anything is better than invalid, timezone is best
49 if (!rhs.isValid() || lhs.timeSpec() == Qt::TimeZone) {
50 return lhs;
51 }
52 if (!lhs.isValid() || rhs.timeSpec() == Qt::TimeZone) {
53 return rhs;
54 }
55
56 // UTC offset it better than local time
57 if (lhs.timeSpec() == Qt::OffsetFromUTC || rhs.timeSpec() == Qt::LocalTime) {
58 return lhs;
59 }
60 return rhs;
61}
62
63QDateTime MergeUtil::mergeDateTimeMax(const QDateTime &lhs, const QDateTime &rhs)
64{
65 // if only one side is valid, prefer that one
66 if (!lhs.isValid()) {
67 return rhs;
68 }
69 if (!rhs.isValid()) {
70 return lhs;
71 }
72
73 auto dt = isBefore(lhs, rhs) ? rhs : lhs;
74 if (dt.timeSpec() == Qt::TimeZone) {
75 return dt;
76 }
77
78 // recover timezone of we can
79 if (lhs.timeSpec() == Qt::TimeZone) {
80 dt.setTimeZone(lhs.timeZone());
81 return dt;
82 } else if (rhs.timeSpec() == Qt::TimeZone) {
83 dt.setTimeZone(rhs.timeZone());
84 return dt;
85 }
86
87 // recover UTC offset if we can
88 if (dt.timeSpec() == Qt::OffsetFromUTC) {
89 return dt;
90 } else if (lhs.timeSpec() == Qt::OffsetFromUTC) {
92 } else if (rhs.timeSpec() == Qt::OffsetFromUTC) {
94 }
95
96 return dt;
97}
98
99static bool containsNonAscii(QStringView s)
100{
101 for (const auto c : s) {
102 if (c.row() != 0 || c.cell() > 127) {
103 return true;
104 }
105 }
106
107 return false;
108}
109
110static bool isMixedCase(QStringView s)
111{
112 const auto letterCount = std::count_if(s.begin(), s.end(), [](auto c) { return c.isLetter(); });
113 const auto upperCount = std::count_if(s.begin(), s.end(), [](auto c) { return c.isUpper(); });
114 return upperCount != letterCount && upperCount != 0;
115}
116
117static bool containsParantheses(QStringView s)
118{
119 return s.contains(u'(') && s.contains(u')');
120}
121
122
123QString MergeUtil::mergeString(const QString &lhs, const QString &rhs)
124{
125 // prefer Unicode over ASCII normalization
126 const auto lhsNonAscii = containsNonAscii(lhs);
127 const auto rhsNonAscii = containsNonAscii(rhs);
128 if (lhsNonAscii && !rhsNonAscii) {
129 return lhs;
130 }
131 if (!lhsNonAscii && rhsNonAscii) {
132 return rhs;
133 }
134
135 // prefer better casing
136 const auto lhsMixedCase = isMixedCase(lhs);
137 const auto rhsMixedCase = isMixedCase(rhs);
138 if (lhsMixedCase && !rhsMixedCase) {
139 return lhs;
140 }
141 if (!lhsMixedCase && rhsMixedCase) {
142 return rhs;
143 }
144
145 if (lhs.size() == rhs.size()) {
146 return lhs < rhs ? lhs : rhs;
147 }
148
149 // Prefer strings without parantheses
150 bool lhsParan = containsParantheses(lhs);
151 bool rhsParan = containsParantheses(rhs);
152 if (lhsParan && !rhsParan) {
153 return rhs;
154 }
155 if (rhsParan && !lhsParan) {
156 return lhs;
157 }
158
159 // Prefer longer string
160 return lhs.size() < rhs.size() ? rhs : lhs;
161}
bool isBefore(const QVariant &lhs, const QVariant &rhs)
Query operations and data types for accessing realtime public transport information from online servi...
bool isValid() const const
int offsetFromUtc() const const
void setTimeZone(const QTimeZone &toZone)
Qt::TimeSpec timeSpec() const const
QTimeZone timeZone() const const
qsizetype size() const const
const_iterator begin() const const
bool contains(QChar c, Qt::CaseSensitivity cs) const const
const_iterator end() const const
LocalTime
QTimeZone fromSecondsAheadOfUtc(int offset)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Nov 22 2024 12:10:39 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.