File indexing completed on 2024-04-21 03:52:45

0001 /*
0002   This file is part of the kcalcore library.
0003 
0004   SPDX-FileCopyrightText: 2001 Cornelius Schumacher <schumacher@kde.org>
0005   SPDX-FileCopyrightText: 2007 David Jarvie <djarvie@kde.org>
0006 
0007   SPDX-License-Identifier: LGPL-2.0-or-later
0008 */
0009 /**
0010   @file
0011   This file is part of the API for handling calendar data and
0012   defines the Duration class.
0013 
0014   @brief
0015   Represents a span of time measured in seconds.
0016 
0017   @author Cornelius Schumacher \<schumacher@kde.org\>
0018   @author David Jarvie \<djarvie@kde.org\>
0019 */
0020 #include "duration.h"
0021 
0022 #include <QDateTime>
0023 #include <QTimeZone>
0024 
0025 using namespace KCalendarCore;
0026 
0027 /**
0028   Private class that helps to provide binary compatibility between releases.
0029   @internal
0030 */
0031 //@cond PRIVATE
0032 class Q_DECL_HIDDEN KCalendarCore::Duration::Private
0033 {
0034 public:
0035     int seconds() const
0036     {
0037         return mDaily ? mDuration * 86400 : mDuration;
0038     }
0039     int mDuration; // number of seconds or days in the duration
0040     bool mDaily = false; // specified in terms of days rather than seconds
0041 };
0042 //@endcond
0043 
0044 Duration::Duration()
0045     : d(new KCalendarCore::Duration::Private())
0046 {
0047 }
0048 
0049 Duration::Duration(const QDateTime &start, const QDateTime &end)
0050     : d(new KCalendarCore::Duration::Private())
0051 {
0052     if (start.time() == end.time() && start.timeZone() == end.timeZone()) {
0053         d->mDuration = start.daysTo(end);
0054         d->mDaily = true;
0055     } else {
0056         d->mDuration = start.secsTo(end);
0057         d->mDaily = false;
0058     }
0059 }
0060 
0061 Duration::Duration(const QDateTime &start, const QDateTime &end, Type type)
0062     : d(new KCalendarCore::Duration::Private())
0063 {
0064     if (type == Days) {
0065         QDateTime endSt(end.toTimeZone(start.timeZone()));
0066         d->mDuration = start.daysTo(endSt);
0067         if (d->mDuration) {
0068             // Round down to whole number of days if necessary
0069             if (start < endSt) {
0070                 if (endSt.time() < start.time()) {
0071                     --d->mDuration;
0072                 }
0073             } else {
0074                 if (endSt.time() > start.time()) {
0075                     ++d->mDuration;
0076                 }
0077             }
0078         }
0079         d->mDaily = true;
0080     } else {
0081         d->mDuration = start.secsTo(end);
0082         d->mDaily = false;
0083     }
0084 }
0085 
0086 Duration::Duration(int duration, Type type)
0087     : d(new KCalendarCore::Duration::Private())
0088 {
0089     d->mDuration = duration;
0090     d->mDaily = (type == Days);
0091 }
0092 
0093 Duration::Duration(const Duration &duration)
0094     : d(new KCalendarCore::Duration::Private(*duration.d))
0095 {
0096 }
0097 
0098 Duration::~Duration()
0099 {
0100     delete d;
0101 }
0102 
0103 Duration &Duration::operator=(const Duration &duration)
0104 {
0105     // check for self assignment
0106     if (&duration == this) {
0107         return *this;
0108     }
0109 
0110     *d = *duration.d;
0111     return *this;
0112 }
0113 
0114 Duration::operator bool() const
0115 {
0116     return d->mDuration;
0117 }
0118 
0119 bool Duration::operator<(const Duration &other) const
0120 {
0121     if (d->mDaily == other.d->mDaily) {
0122         // guard against integer overflow for two daily durations
0123         return d->mDuration < other.d->mDuration;
0124     }
0125     return d->seconds() < other.d->seconds();
0126 }
0127 
0128 bool Duration::operator==(const Duration &other) const
0129 {
0130     // Note: daily and non-daily durations are always unequal, since a day's
0131     // duration may differ from 24 hours if it happens to span a daylight saving
0132     // time change.
0133     return d->mDuration == other.d->mDuration && d->mDaily == other.d->mDaily;
0134 }
0135 
0136 Duration &Duration::operator+=(const Duration &other)
0137 {
0138     if (d->mDaily == other.d->mDaily) {
0139         d->mDuration += other.d->mDuration;
0140     } else if (d->mDaily) {
0141         d->mDuration = d->mDuration * 86400 + other.d->mDuration;
0142         d->mDaily = false;
0143     } else {
0144         d->mDuration += other.d->mDuration + 86400;
0145     }
0146     return *this;
0147 }
0148 
0149 Duration Duration::operator-() const
0150 {
0151     return Duration(-d->mDuration, (d->mDaily ? Days : Seconds));
0152 }
0153 
0154 Duration &Duration::operator-=(const Duration &duration)
0155 {
0156     return operator+=(-duration);
0157 }
0158 
0159 Duration &Duration::operator*=(int value)
0160 {
0161     d->mDuration *= value;
0162     return *this;
0163 }
0164 
0165 Duration &Duration::operator/=(int value)
0166 {
0167     d->mDuration /= value;
0168     return *this;
0169 }
0170 
0171 QDateTime Duration::end(const QDateTime &start) const
0172 {
0173     return d->mDaily ? start.addDays(d->mDuration) : start.addSecs(d->mDuration);
0174 }
0175 
0176 Duration::Type Duration::type() const
0177 {
0178     return d->mDaily ? Days : Seconds;
0179 }
0180 
0181 bool Duration::isDaily() const
0182 {
0183     return d->mDaily;
0184 }
0185 
0186 int Duration::asSeconds() const
0187 {
0188     return d->seconds();
0189 }
0190 
0191 int Duration::asDays() const
0192 {
0193     return d->mDaily ? d->mDuration : d->mDuration / 86400;
0194 }
0195 
0196 int Duration::value() const
0197 {
0198     return d->mDuration;
0199 }
0200 
0201 bool Duration::isNull() const
0202 {
0203     return d->mDuration == 0;
0204 }
0205 
0206 QDataStream &KCalendarCore::operator<<(QDataStream &out, const KCalendarCore::Duration &duration)
0207 {
0208     out << duration.d->mDuration << duration.d->mDaily;
0209     return out;
0210 }
0211 
0212 QDataStream &KCalendarCore::operator>>(QDataStream &in, KCalendarCore::Duration &duration)
0213 {
0214     in >> duration.d->mDuration >> duration.d->mDaily;
0215     return in;
0216 }