MailJDTourDownloadDocsQualityTestsCoverage

Which source lines and branches the tests execute. Lines 91.5 %, branches 75.0 % (minimum 85 % and 72 %). main @ 399ffe3d · 21 October 2026 · pipeline 7238.

GCC Code Coverage Report


Directory: src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 2 / 0 / 2
Functions: 100.0% 2 / 0 / 2
Branches: -% 0 / 0 / 0

data/ICalTime.h
Line Branch Exec Source
1 #pragma once
2
3 #include "ICalendar.h"
4
5 #include <QDateTime>
6 #include <QHash>
7 #include <QList>
8 #include <QString>
9 #include <QTimeZone>
10
11 // iCalendar DATE / DATE-TIME values and time-zone resolution (Sprint 93
12 // S93.1.2, CAL-TZ).
13 //
14 // MailJD keeps three kinds of DATE-TIME values, distinguished by the
15 // QDateTime it produces and by the zone id stored next to the instant in
16 // calendar.db (`tz_start`/`tz_end`):
17 // "" UTC ("…Z") QDateTime in UTC
18 // "floating" no zone (local wall clock) QDateTime in local time
19 // "<zone id>" TZID, resolved to an IANA zone QDateTime in that zone
20 // DATE values (all-day) are stored at UTC midnight with an empty zone id.
21 //
22 // TZID resolution order: IANA id (also as the tail of a "/mozilla.org/…"
23 // path), Windows zone name, the resource's VTIMEZONE (matched to the IANA
24 // zone with identical transitions over ±2 years, preferring X-LIC-LOCATION,
25 // the system zone and zones whose city appears in the TZID), else a fixed
26 // offset from that VTIMEZONE; an unknown TZID without definition is
27 // treated as floating. Every fallback logs under mailjd.calendar.tz.
28 namespace ICalTime {
29
30 inline const QString kFloating = QStringLiteral("floating");
31
32 class ZoneResolver {
33 public:
34 508 ZoneResolver() = default;
35 // `calendar` is the VCALENDAR whose VTIMEZONE components define custom ids.
36 explicit ZoneResolver(const ICal::Component &calendar);
37 // Invalid QTimeZone = treat the value as floating.
38 QTimeZone resolve(const QString &tzid) const;
39
40 private:
41 QHash<QString, ICal::Component> m_definitions; // unescaped TZID -> VTIMEZONE
42 mutable QHash<QString, QTimeZone> m_cache;
43 };
44
45 struct Value {
46 QDateTime dateTime; // see the table above
47 bool dateOnly = false; // VALUE=DATE
48 bool floating = false;
49 1504 bool valid() const { return dateTime.isValid(); }
50 };
51
52 // One DATE / DATE-TIME text with the TZID of its property.
53 Value parseValue(const QString &text, const QString &tzid, bool forceDate,
54 const ZoneResolver &resolver);
55 // A property (DTSTART, DTEND, RECURRENCE-ID, …) incl. VALUE/TZID params.
56 Value parseProperty(const ICal::Property &property, const ZoneResolver &resolver);
57 // Multi-valued EXDATE / RDATE property; PERIOD values use their start.
58 QList<Value> parseList(const ICal::Property &property, const ZoneResolver &resolver);
59
60 // Zone id as stored (see table); "" for UTC and DATE values.
61 QString zoneId(const QDateTime &dateTime, bool dateOnly);
62 // Rebuilds a stored value: the instant in its zone (or local / UTC).
63 QDateTime fromStored(qint64 secondsSinceEpoch, const QString &zoneId);
64 // The QTimeZone a stored zone id denotes (invalid for "" and floating).
65 QTimeZone zoneForId(const QString &zoneId);
66
67 // Renders `dateTime` into `property` (value + VALUE/TZID parameters).
68 // `tzid` is the parameter text to use for zoned values (the original TZID
69 // when the zone did not change, else the IANA id).
70 void writeProperty(ICal::Property *property, const QDateTime &dateTime, bool dateOnly,
71 const QString &tzid);
72 QString formatValue(const QDateTime &dateTime, bool dateOnly);
73
74 // RFC 5545 basic-format DATE ("yyyyMMdd", exactly 8 characters) and
75 // DATE-TIME ("yyyyMMddTHHmmss", exactly 15) read as a plain wall clock: no
76 // zone, no DST adjustment. False for other text or an invalid date/time.
77 // QDateTime::fromString() is not used: it builds a local time first (moving
78 // wall clocks inside a DST gap of the system zone) and costs ~0.3 ms a call.
79 bool parseBasicDate(QStringView text, QDate *date);
80 bool parseBasicDateTime(QStringView text, QDate *date, QTime *time);
81
82 // Wall clock of `naive` (date+time, zone ignored) in `zone`; a time in a DST
83 // gap moves forward by the gap, a time in a fold takes the earlier instant
84 // (RFC 5545 §3.3.5). Invalid zone = local time (floating).
85 QDateTime fromWallClock(const QDate &date, const QTime &time, const QTimeZone &zone);
86
87 // A VTIMEZONE for `zone` around `year`: STANDARD/DAYLIGHT with yearly RRULEs
88 // when the zone follows a fixed yearly pattern, else explicit transitions
89 // for year-1 … year+5.
90 ICal::Component vtimezoneFor(const QTimeZone &zone, int year);
91
92 } // namespace ICalTime
93