1/*
2 This file is part of the kcalcore library.
3
4 Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
5 Copyright (c) 2007 David Jarvie <djarvie@kde.org>
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public License
18 along with this library; see the file COPYING.LIB. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21*/
22/**
23 @file
24 This file is part of the API for handling calendar data and
25 defines the Duration class.
26
27 @brief
28 Represents a span of time measured in seconds.
29
30 @author Cornelius Schumacher \<schumacher@kde.org\>
31 @author David Jarvie \<software@astrojar.org.uk\>
32*/
33#include "duration.h"
34#include <KDateTime>
35
36#include <QTime>
37
38using namespace KCalCore;
39
40/**
41 Private class that helps to provide binary compatibility between releases.
42 @internal
43*/
44//@cond PRIVATE
45class KCalCore::Duration::Private
46{
47public:
48 int seconds() const {
49 return mDaily ? mDuration * 86400 : mDuration;
50 }
51 int mDuration; // number of seconds or days in the duration
52 bool mDaily; // specified in terms of days rather than seconds
53};
54//@endcond
55
56Duration::Duration()
57 : d(new KCalCore::Duration::Private())
58{
59}
60
61Duration::Duration(const KDateTime &start, const KDateTime &end)
62 : d(new KCalCore::Duration::Private())
63{
64 if (start.time() == end.time() && start.timeSpec() == end.timeSpec()) {
65 d->mDuration = start.daysTo(end);
66 d->mDaily = true;
67 } else {
68 d->mDuration = start.secsTo(end);
69 d->mDaily = false;
70 }
71}
72
73Duration::Duration(const KDateTime &start, const KDateTime &end, Type type)
74 : d(new KCalCore::Duration::Private())
75{
76 if (type == Days) {
77 KDateTime endSt(end.toTimeSpec(start));
78 d->mDuration = start.daysTo(endSt);
79 if (d->mDuration) {
80 // Round down to whole number of days if necessary
81 if (start < endSt) {
82 if (endSt.time() < start.time()) {
83 --d->mDuration;
84 }
85 } else {
86 if (endSt.time() > start.time()) {
87 ++d->mDuration;
88 }
89 }
90 }
91 d->mDaily = true;
92 } else {
93 d->mDuration = start.secsTo(end);
94 d->mDaily = false;
95 }
96}
97
98Duration::Duration(int duration, Type type)
99 : d(new KCalCore::Duration::Private())
100{
101 d->mDuration = duration;
102 d->mDaily = (type == Days);
103}
104
105Duration::Duration(const Duration &duration)
106 : d(new KCalCore::Duration::Private(*duration.d))
107{
108}
109
110Duration::~Duration()
111{
112 delete d;
113}
114
115Duration &Duration::operator=(const Duration &duration)
116{
117 // check for self assignment
118 if (&duration == this) {
119 return *this;
120 }
121
122 *d = *duration.d;
123 return *this;
124}
125
126Duration::operator bool() const
127{
128 return d->mDuration;
129}
130
131bool Duration::operator<(const Duration &other) const
132{
133 if (d->mDaily == other.d->mDaily) {
134 // guard against integer overflow for two daily durations
135 return d->mDuration < other.d->mDuration;
136 }
137 return d->seconds() < other.d->seconds();
138}
139
140bool Duration::operator==(const Duration &other) const
141{
142 // Note: daily and non-daily durations are always unequal, since a day's
143 // duration may differ from 24 hours if it happens to span a daylight saving
144 // time change.
145 return d->mDuration == other.d->mDuration &&
146 d->mDaily == other.d->mDaily;
147}
148
149Duration &Duration::operator+=(const Duration &other)
150{
151 if (d->mDaily == other.d->mDaily) {
152 d->mDuration += other.d->mDuration;
153 } else if (d->mDaily) {
154 d->mDuration = d->mDuration * 86400 + other.d->mDuration;
155 d->mDaily = false;
156 } else {
157 d->mDuration += other.d->mDuration + 86400;
158 }
159 return *this;
160}
161
162Duration Duration::operator-() const
163{
164 return Duration(-d->mDuration, (d->mDaily ? Days : Seconds));
165}
166
167Duration &Duration::operator-=(const Duration &duration)
168{
169 return operator+=(-duration);
170}
171
172Duration &Duration::operator*=(int value)
173{
174 d->mDuration *= value;
175 return *this;
176}
177
178Duration &Duration::operator/=(int value)
179{
180 d->mDuration /= value;
181 return *this;
182}
183
184KDateTime Duration::end(const KDateTime &start) const
185{
186 return d->mDaily ? start.addDays(d->mDuration)
187 : start.addSecs(d->mDuration);
188}
189
190Duration::Type Duration::type() const
191{
192 return d->mDaily ? Days : Seconds;
193}
194
195bool Duration::isDaily() const
196{
197 return d->mDaily;
198}
199
200int Duration::asSeconds() const
201{
202 return d->seconds();
203}
204
205int Duration::asDays() const
206{
207 return d->mDaily ? d->mDuration : d->mDuration / 86400;
208}
209
210int Duration::value() const
211{
212 return d->mDuration;
213}
214
215QDataStream &KCalCore::operator<<(QDataStream &out, const KCalCore::Duration &duration)
216{
217 out << duration.d->mDuration << duration.d->mDaily;
218 return out;
219}
220
221QDataStream &KCalCore::operator>>(QDataStream &in, KCalCore::Duration &duration)
222{
223 in >> duration.d->mDuration >> duration.d->mDaily;
224 return in;
225}
226