KanoopCommonQt 2.1.1
Kanoop foundational Qt utility library
Loading...
Searching...
No Matches
daterange.h
1/**
2 * @brief A time range defined by a start and end QDateTime.
3 *
4 * DateRange represents a contiguous span of time. It supports arithmetic with TimeSpan,
5 * overlap/containment queries, and consolidation of overlapping ranges via DateRange::List.
6 */
7#ifndef DATERANGE_H
8#define DATERANGE_H
9#include <QDateTime>
10
11#include <Kanoop/timespan.h>
12#include "kanoopcommon.h"
13
14/**
15 * @brief Represents a contiguous date/time range with start and end timestamps.
16 */
17class KANOOP_EXPORT DateRange
18{
19public:
20 /** @brief Default constructor — creates an invalid (empty) date range. */
22
23 /**
24 * @brief Construct a DateRange from explicit start and end times.
25 * @param startTime Range begin timestamp
26 * @param endTime Range end timestamp
27 */
28 DateRange(const QDateTime& startTime, const QDateTime& endTime) :
29 _startTime(startTime), _endTime(endTime) {}
30
31 /**
32 * @brief Construct a DateRange from a start time and duration.
33 * @param startTime Range begin timestamp
34 * @param duration Length of the range
35 */
36 DateRange(const QDateTime& startTime, const TimeSpan& duration) :
37 _startTime(startTime), _endTime(startTime.addMSecs(duration.totalMilliseconds())) {}
38
39 /** @brief Copy constructor.
40 * @param other DateRange to copy. */
41 DateRange(const DateRange& other);
42
43 /**
44 * @brief Create a DateRange centred on a midpoint with the given duration.
45 * @param midpoint Centre of the range
46 * @param duration Total length of the range
47 * @return DateRange symmetrically straddling midpoint
48 */
49 static DateRange fromMidpoint(const QDateTime& midpoint, const TimeSpan& duration);
50
51 /** @brief Assignment operator.
52 * @param other DateRange to assign from.
53 * @return Reference to this. */
55
56 /**
57 * @brief Shift both endpoints forward by a TimeSpan.
58 * @param other Amount to add
59 * @return New shifted DateRange
60 */
61 DateRange operator+(const TimeSpan& other) const;
62
63 /**
64 * @brief Shift both endpoints backward by a TimeSpan.
65 * @param other Amount to subtract
66 * @return New shifted DateRange
67 */
68 DateRange operator-(const TimeSpan& other) const;
69
70 /** @brief Shift both endpoints forward by a TimeSpan in place.
71 * @param other Amount to add. */
72 void operator+=(const TimeSpan& other);
73 /** @brief Shift both endpoints backward by a TimeSpan in place.
74 * @param other Amount to subtract. */
75 void operator-=(const TimeSpan& other);
76
77 /** @brief Equality comparison.
78 * @param other DateRange to compare.
79 * @return True if both endpoints are equal. */
80 bool operator==(const DateRange& other) const;
81 /** @brief Inequality comparison.
82 * @param other DateRange to compare.
83 * @return True if the ranges differ. */
84 bool operator!=(const DateRange& other) const;
85
86 /**
87 * @brief Return the range start time.
88 * @return Start QDateTime
89 */
90 QDateTime startTime() const { return _startTime; }
91
92 /**
93 * @brief Set the range start time.
94 * @param value New start QDateTime
95 */
96 void setStartTime(const QDateTime& value) { _startTime = value; }
97
98 /**
99 * @brief Return the range end time.
100 * @return End QDateTime
101 */
102 QDateTime endTime() const { return _endTime; }
103
104 /**
105 * @brief Set the range end time.
106 * @param value New end QDateTime
107 */
108 void setEndTime(const QDateTime& value) { _endTime = value; }
109
110 /**
111 * @brief Return the absolute duration of the range.
112 * @return TimeSpan between start and end
113 */
114 TimeSpan duration() const { return TimeSpan::absDiff(_startTime, _endTime); }
115
116 /**
117 * @brief Return the midpoint of the range.
118 * @return QDateTime at the centre of the range
119 */
120 QDateTime midpoint() const { return _startTime.addMSecs((duration() / 2).totalMilliseconds()); }
121
122 /**
123 * @brief Test whether a timestamp falls within the range (inclusive).
124 * @param time Timestamp to test
125 * @return true if time >= startTime && time <= endTime
126 */
127 bool contains(const QDateTime& time) const { return time >= _startTime && time <= _endTime; }
128
129 /**
130 * @brief Test whether another DateRange is entirely contained within this one.
131 * @param other Range to test
132 * @return true if other is fully within this range
133 */
134 bool contains(const DateRange& other) const { return contains(other.startTime()) && contains(other.endTime()); }
135
136 /**
137 * @brief Test whether another DateRange is intersects with this one.
138 * @param other Range to test
139 * @return true if other is fully within this range
140 */
141 bool intersects(const DateRange& other) const;
142
143 /**
144 * @brief Return the intersection of this range with another.
145 * @param other Range to intersect with
146 * @return Overlapping sub-range, or an invalid DateRange if no overlap
147 */
148 DateRange subRange(const DateRange& other) const;
149
150 /**
151 * @brief Return the union of this range and another.
152 * @param other Range to merge with
153 * @return DateRange spanning both ranges
154 */
155 DateRange merged(const DateRange& other) const;
156
157 /**
158 * @brief Return the union of two ranges (static convenience overload).
159 * @param a First range
160 * @param b Second range
161 * @return DateRange spanning both
162 */
163 static DateRange merged(const DateRange& a, const DateRange& b) { return a.merged(b); }
164
165 /**
166 * @brief Format the range as a human-readable string.
167 * @return String representation of start and end times
168 */
169 QString toString() const;
170
171 /**
172 * @brief Check whether both endpoints are valid QDateTime values.
173 * @return true if startTime and endTime are valid
174 */
175 bool isValid() const { return _startTime.isValid() && _endTime.isValid(); }
176
177 /**
178 * @brief A sortable, consolidatable list of DateRange objects.
179 */
180 class List : public QList<DateRange>
181 {
182 public:
183 /**
184 * @brief Return a new list with overlapping/adjacent ranges merged.
185 * @return Consolidated list sorted by start time
186 */
188 {
189 List result;
190 List sorted = *this;
191 std::sort(sorted.begin(), sorted.end(), [](const DateRange& a, const DateRange& b) { return a.startTime() < b.startTime(); });
192
193 if(sorted.count() < 2) {
194 return sorted;
195 }
196
197 DateRange current = first();
198
199 for (int i = 1; i < size(); ++i) {
200 const DateRange& next = (*this)[i];
201
202 if (current.endTime() >= next.startTime()) {
203 current = DateRange(
204 current.startTime(),
205 std::max(current.endTime(), next.endTime())
206 );
207 }
208 else {
209 result.append(current);
210 current = next;
211 }
212 }
213 result.append(current);
214
215 return result;
216 }
217 };
218
219private:
220 QDateTime _startTime;
221 QDateTime _endTime;
222};
223
224#endif // DATERANGE_H
A sortable, consolidatable list of DateRange objects.
Definition daterange.h:181
List consolidated() const
Return a new list with overlapping/adjacent ranges merged.
Definition daterange.h:187
A time range defined by a start and end QDateTime.
Definition daterange.h:18
DateRange(const QDateTime &startTime, const TimeSpan &duration)
Construct a DateRange from a start time and duration.
Definition daterange.h:36
void setStartTime(const QDateTime &value)
Set the range start time.
Definition daterange.h:96
static DateRange merged(const DateRange &a, const DateRange &b)
Return the union of two ranges (static convenience overload).
Definition daterange.h:163
DateRange subRange(const DateRange &other) const
Return the intersection of this range with another.
DateRange merged(const DateRange &other) const
Return the union of this range and another.
bool intersects(const DateRange &other) const
Test whether another DateRange is intersects with this one.
DateRange operator-(const TimeSpan &other) const
Shift both endpoints backward by a TimeSpan.
DateRange(const DateRange &other)
Copy constructor.
bool contains(const QDateTime &time) const
Test whether a timestamp falls within the range (inclusive).
Definition daterange.h:127
static DateRange fromMidpoint(const QDateTime &midpoint, const TimeSpan &duration)
Create a DateRange centred on a midpoint with the given duration.
void operator+=(const TimeSpan &other)
Shift both endpoints forward by a TimeSpan in place.
void setEndTime(const QDateTime &value)
Set the range end time.
Definition daterange.h:108
DateRange operator+(const TimeSpan &other) const
Shift both endpoints forward by a TimeSpan.
DateRange & operator=(const DateRange &other)
Assignment operator.
QDateTime endTime() const
Return the range end time.
Definition daterange.h:102
void operator-=(const TimeSpan &other)
Shift both endpoints backward by a TimeSpan in place.
DateRange(const QDateTime &startTime, const QDateTime &endTime)
Construct a DateRange from explicit start and end times.
Definition daterange.h:28
bool isValid() const
Check whether both endpoints are valid QDateTime values.
Definition daterange.h:175
bool operator==(const DateRange &other) const
Equality comparison.
QString toString() const
Format the range as a human-readable string.
DateRange()
Default constructor — creates an invalid (empty) date range.
Definition daterange.h:21
QDateTime midpoint() const
Return the midpoint of the range.
Definition daterange.h:120
bool contains(const DateRange &other) const
Test whether another DateRange is entirely contained within this one.
Definition daterange.h:134
QDateTime startTime() const
Return the range start time.
Definition daterange.h:90
TimeSpan duration() const
Return the absolute duration of the range.
Definition daterange.h:114
bool operator!=(const DateRange &other) const
Inequality comparison.
TimeSpan.
Definition timespan.h:42
static TimeSpan absDiff(const QDateTime &t1, const QDateTime &t2)
Compute the absolute (non-negative) difference between two QDateTime values.