kplato

kptduration.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2001 Thomas Zander zander@kde.org
3 Copyright (C) 2004, 2005 Dag Andersen <danders@get2net.dk>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19*/
20
21#include "kptduration.h"
22#include "kptdatetime.h"
23
24#include <tdeglobal.h>
25#include <tdelocale.h>
26#include <kdebug.h>
27#include <tqregexp.h>
28
29namespace KPlato
30{
31
32// Set the value of Duration::zeroDuration to zero.
33const Duration Duration::zeroDuration( 0, 0, 0 );
34
35Duration::Duration() {
36 m_ms = 0;
37}
38
39Duration::Duration(const Duration &d) {
40 m_ms = d.m_ms;
41}
42
43Duration::Duration(unsigned d, unsigned h, unsigned m, unsigned s, unsigned ms) {
44 m_ms = ms;
45 m_ms += static_cast<TQ_INT64>(s) * 1000; // cast to avoid potential overflow problem
46 m_ms += static_cast<TQ_INT64>(m) * 60 * 1000;
47 m_ms += static_cast<TQ_INT64>(h) * 60 * 60 * 1000;
48 m_ms += static_cast<TQ_INT64>(d) * 24 * 60 * 60 * 1000;
49}
50
51Duration::Duration(TQ_INT64 seconds) {
52 m_ms = seconds * 1000;
53}
54
55Duration::~Duration() {
56}
57
58void Duration::add(const Duration &delta) {
59 m_ms += delta.m_ms;
60}
61
62void Duration::add(TQ_INT64 delta) {
63 TQ_INT64 tmp = m_ms + delta;
64 if (tmp < 0) {
65 kdDebug()<<k_funcinfo<<"Underflow"<<(long int)delta<<" from "<<this->toString()<<endl;
66 m_ms = 0;
67 return;
68 }
69 m_ms = tmp;
70}
71
72void Duration::subtract(const Duration &delta) {
73 if (m_ms < delta.m_ms) {
74 kdDebug()<<k_funcinfo<<"Underflow"<<delta.toString()<<" from "<<this->toString()<<endl;
75 m_ms = 0;
76 return;
77 }
78 m_ms -= delta.m_ms;
79}
80
81Duration Duration::operator*(int unit) const {
82 Duration dur(*this);
83 if (unit < 0) {
84 kdDebug()<<k_funcinfo<<"Underflow"<<unit<<" from "<<this->toString()<<endl;
85 }
86 else {
87 dur.m_ms = m_ms * unit; //FIXME
88 }
89 return dur;
90}
91
92Duration Duration::operator/(int unit) const {
93 Duration dur(*this);
94 if (unit <= 0) {
95 kdDebug()<<k_funcinfo<<"Underflow"<<unit<<" from "<<this->toString()<<endl;
96 }
97 else {
98 dur.m_ms = m_ms / unit; //FIXME
99 }
100 return dur;
101}
102
103Duration Duration::operator*(const double value) const {
104 Duration dur(*this);
105 dur.m_ms = TQABS(m_ms * (TQ_INT64)value);
106 return dur;
107}
108
109double Duration::operator/(const Duration &d) const {
110 if (d == zeroDuration) {
111 kdDebug()<<k_funcinfo<<"Devide by zero: "<<this->toString()<<endl;
112 return 0.0;
113 }
114 return (double)(m_ms) / (double)(d.m_ms);
115}
116
117TQString Duration::toString(Format format) const {
118 TQ_INT64 ms;
119 double days;
120 unsigned hours;
121 unsigned minutes;
122 unsigned seconds;
123 double f;
124 TQString result;
125
126 switch (format) {
127 case Format_Hour:
128 ms = m_ms;
129 hours = ms / (1000 * 60 * 60);
130 ms -= (TQ_INT64)hours * (1000 * 60 * 60);
131 minutes = ms / (1000 * 60);
132 result = TQString("%1h%2m").arg(hours).arg(minutes);
133 break;
134 case Format_Day:
135 days = m_ms / (1000 * 60 * 60 * 24.0);
136 result = TQString("%1d").arg(TQString::number(days, 'f', 4));
137 break;
138 case Format_DayTime:
139 ms = m_ms;
140 days = m_ms / (1000 * 60 * 60 * 24);
141 ms -= (TQ_INT64)days * (1000 * 60 * 60 * 24);
142 hours = ms / (1000 * 60 * 60);
143 ms -= (TQ_INT64)hours * (1000 * 60 * 60);
144 minutes = ms / (1000 * 60);
145 ms -= minutes * (1000 * 60);
146 seconds = ms / (1000);
147 ms -= seconds * (1000);
148 result.sprintf("%u %02u:%02u:%02u.%u", (unsigned)days, hours, minutes, seconds, (unsigned)ms);
149 break;
150 case Format_HourFraction:
151 result = TDEGlobal::locale()->formatNumber(toDouble(Unit_h), 2);
152 break;
153 // i18n
154 case Format_i18nHour:
155 ms = m_ms;
156 hours = ms / (1000 * 60 * 60);
157 ms -= (TQ_INT64)hours * (1000 * 60 * 60);
158 minutes = ms / (1000 * 60);
159 result = i18n("<hours>h:<minutes>m", "%1h:%2m").arg(hours).arg(minutes);
160 break;
161 case Format_i18nDay:
162 result = TDEGlobal::locale()->formatNumber(toDouble(Unit_d), 2);
163 break;
164 case Format_i18nDayTime:
165 ms = m_ms;
166 days = m_ms / (1000 * 60 * 60 * 24);
167 ms -= (TQ_INT64)days * (1000 * 60 * 60 * 24);
168 hours = ms / (1000 * 60 * 60);
169 ms -= (TQ_INT64)hours * (1000 * 60 * 60);
170 minutes = ms / (1000 * 60);
171 ms -= minutes * (1000 * 60);
172 seconds = ms / (1000);
173 ms -= seconds * (1000);
174 if (days == 0) {
175 result = toString(Format_i18nHour);
176 } else {
177 result = i18n("<days>d <hours>h:<minutes>m", "%1d %2h:%3m").arg(days).arg(hours).arg(minutes);
178 }
179 break;
180 case Format_i18nHourFraction:
181 result = TDEGlobal::locale()->formatNumber(toDouble(Unit_h), 2);
182 break;
183 default:
184 kdFatal()<<k_funcinfo<<"Unknown format"<<endl;
185 break;
186 }
187 return result;
188}
189
190Duration Duration::fromString(const TQString &s, Format format, bool *ok) {
191 if (ok) *ok = false;
192 TQRegExp matcher;
193 Duration tmp;
194 switch (format) {
195 case Format_Hour: {
196 matcher.setPattern("^(\\d*)h(\\d*)m$" );
197 int pos = matcher.search(s);
198 if (pos > -1) {
199 tmp.addHours(matcher.cap(1).toUInt());
200 tmp.addMinutes(matcher.cap(2).toUInt());
201 if (ok) *ok = true;
202 }
203 break;
204 }
205 case Format_DayTime: {
206 matcher.setPattern("^(\\d*) (\\d*):(\\d*):(\\d*)\\.(\\d*)$" );
207 int pos = matcher.search(s);
208 if (pos > -1) {
209 tmp.addDays(matcher.cap(1).toUInt());
210 tmp.addHours(matcher.cap(2).toUInt());
211 tmp.addMinutes(matcher.cap(3).toUInt());
212 tmp.addSeconds(matcher.cap(4).toUInt());
213 tmp.addMilliseconds(matcher.cap(5).toUInt());
214 if (ok) *ok = true;
215 }
216 break;
217 }
218 case Format_HourFraction: {
219 // should be in double format
220 bool res;
221 double f = TDEGlobal::locale()->readNumber(s, &res);
222 if (ok) *ok = res;
223 if (res) {
224 return Duration((TQ_INT64)(f*3600.0));
225 }
226 break;
227 }
228 default:
229 kdFatal()<<k_funcinfo<<"Unknown format"<<endl;
230 break;
231 }
232 return tmp;
233}
234
235void Duration::get(unsigned *days, unsigned *hours, unsigned *minutes, unsigned *seconds, unsigned *milliseconds) const {
236 TQ_INT64 ms;
237 TQ_INT64 tmp;
238
239 ms = m_ms;
240 tmp = ms / (1000 * 60 * 60 * 24);
241 *days = tmp;
242 ms -= tmp * (1000 * 60 * 60 * 24);
243 tmp = ms / (1000 * 60 * 60);
244 *hours = tmp;
245 ms -= tmp * (1000 * 60 * 60);
246 tmp = ms / (1000 * 60);
247 *minutes = tmp;
248 ms -= tmp * (1000 * 60);
249 tmp = ms / (1000);
250 if (seconds)
251 *seconds = tmp;
252 ms -= tmp * (1000);
253 if (milliseconds)
254 *milliseconds = ms;
255}
256
257} //KPlato namespace
static const Duration zeroDuration
This is useful for occasions where we need a zero duration.