You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/kplato/kptduration.cc

258 lines
7.7 KiB

/* This file is part of the KDE project
Copyright (C) 2001 Thomas Zander zander@kde.org
Copyright (C) 2004, 2005 Dag Andersen <danders@get2net.dk>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "kptduration.h"
#include "kptdatetime.h"
#include <kglobal.h>
#include <klocale.h>
#include <kdebug.h>
#include <tqregexp.h>
namespace KPlato
{
// Set the value of Duration::zeroDuration to zero.
const Duration Duration::zeroDuration( 0, 0, 0 );
Duration::Duration() {
m_ms = 0;
}
Duration::Duration(const Duration &d) {
m_ms = d.m_ms;
}
Duration::Duration(unsigned d, unsigned h, unsigned m, unsigned s, unsigned ms) {
m_ms = ms;
m_ms += static_cast<TQ_INT64>(s) * 1000; // cast to avoid potential overflow problem
m_ms += static_cast<TQ_INT64>(m) * 60 * 1000;
m_ms += static_cast<TQ_INT64>(h) * 60 * 60 * 1000;
m_ms += static_cast<TQ_INT64>(d) * 24 * 60 * 60 * 1000;
}
Duration::Duration(TQ_INT64 seconds) {
m_ms = seconds * 1000;
}
Duration::~Duration() {
}
void Duration::add(const Duration &delta) {
m_ms += delta.m_ms;
}
void Duration::add(TQ_INT64 delta) {
TQ_INT64 tmp = m_ms + delta;
if (tmp < 0) {
kdDebug()<<k_funcinfo<<"Underflow"<<(long int)delta<<" from "<<this->toString()<<endl;
m_ms = 0;
return;
}
m_ms = tmp;
}
void Duration::subtract(const Duration &delta) {
if (m_ms < delta.m_ms) {
kdDebug()<<k_funcinfo<<"Underflow"<<delta.toString()<<" from "<<this->toString()<<endl;
m_ms = 0;
return;
}
m_ms -= delta.m_ms;
}
Duration Duration::operator*(int unit) const {
Duration dur(*this);
if (unit < 0) {
kdDebug()<<k_funcinfo<<"Underflow"<<unit<<" from "<<this->toString()<<endl;
}
else {
dur.m_ms = m_ms * unit; //FIXME
}
return dur;
}
Duration Duration::operator/(int unit) const {
Duration dur(*this);
if (unit <= 0) {
kdDebug()<<k_funcinfo<<"Underflow"<<unit<<" from "<<this->toString()<<endl;
}
else {
dur.m_ms = m_ms / unit; //FIXME
}
return dur;
}
Duration Duration::operator*(const double value) const {
Duration dur(*this);
dur.m_ms = TQABS(m_ms * (TQ_INT64)value);
return dur;
}
double Duration::operator/(const Duration &d) const {
if (d == zeroDuration) {
kdDebug()<<k_funcinfo<<"Devide by zero: "<<this->toString()<<endl;
return 0.0;
}
return (double)(m_ms) / (double)(d.m_ms);
}
TQString Duration::toString(Format format) const {
TQ_INT64 ms;
double days;
unsigned hours;
unsigned minutes;
unsigned seconds;
double f;
TQString result;
switch (format) {
case Format_Hour:
ms = m_ms;
hours = ms / (1000 * 60 * 60);
ms -= (TQ_INT64)hours * (1000 * 60 * 60);
minutes = ms / (1000 * 60);
result = TQString("%1h%2m").arg(hours).arg(minutes);
break;
case Format_Day:
days = m_ms / (1000 * 60 * 60 * 24.0);
result = TQString("%1d").arg(TQString::number(days, 'f', 4));
break;
case Format_DayTime:
ms = m_ms;
days = m_ms / (1000 * 60 * 60 * 24);
ms -= (TQ_INT64)days * (1000 * 60 * 60 * 24);
hours = ms / (1000 * 60 * 60);
ms -= (TQ_INT64)hours * (1000 * 60 * 60);
minutes = ms / (1000 * 60);
ms -= minutes * (1000 * 60);
seconds = ms / (1000);
ms -= seconds * (1000);
result.sprintf("%u %02u:%02u:%02u.%u", (unsigned)days, hours, minutes, seconds, (unsigned)ms);
break;
case Format_HourFraction:
result = TDEGlobal::locale()->formatNumber(toDouble(Unit_h), 2);
break;
// i18n
case Format_i18nHour:
ms = m_ms;
hours = ms / (1000 * 60 * 60);
ms -= (TQ_INT64)hours * (1000 * 60 * 60);
minutes = ms / (1000 * 60);
result = i18n("<hours>h:<minutes>m", "%1h:%2m").arg(hours).arg(minutes);
break;
case Format_i18nDay:
result = TDEGlobal::locale()->formatNumber(toDouble(Unit_d), 2);
break;
case Format_i18nDayTime:
ms = m_ms;
days = m_ms / (1000 * 60 * 60 * 24);
ms -= (TQ_INT64)days * (1000 * 60 * 60 * 24);
hours = ms / (1000 * 60 * 60);
ms -= (TQ_INT64)hours * (1000 * 60 * 60);
minutes = ms / (1000 * 60);
ms -= minutes * (1000 * 60);
seconds = ms / (1000);
ms -= seconds * (1000);
if (days == 0) {
result = toString(Format_i18nHour);
} else {
result = i18n("<days>d <hours>h:<minutes>m", "%1d %2h:%3m").arg(days).arg(hours).arg(minutes);
}
break;
case Format_i18nHourFraction:
result = TDEGlobal::locale()->formatNumber(toDouble(Unit_h), 2);
break;
default:
kdFatal()<<k_funcinfo<<"Unknown format"<<endl;
break;
}
return result;
}
Duration Duration::fromString(const TQString &s, Format format, bool *ok) {
if (ok) *ok = false;
TQRegExp matcher;
Duration tmp;
switch (format) {
case Format_Hour: {
matcher.setPattern("^(\\d*)h(\\d*)m$" );
int pos = matcher.search(s);
if (pos > -1) {
tmp.addHours(matcher.cap(1).toUInt());
tmp.addMinutes(matcher.cap(2).toUInt());
if (ok) *ok = true;
}
break;
}
case Format_DayTime: {
matcher.setPattern("^(\\d*) (\\d*):(\\d*):(\\d*)\\.(\\d*)$" );
int pos = matcher.search(s);
if (pos > -1) {
tmp.addDays(matcher.cap(1).toUInt());
tmp.addHours(matcher.cap(2).toUInt());
tmp.addMinutes(matcher.cap(3).toUInt());
tmp.addSeconds(matcher.cap(4).toUInt());
tmp.addMilliseconds(matcher.cap(5).toUInt());
if (ok) *ok = true;
}
break;
}
case Format_HourFraction: {
// should be in double format
bool res;
double f = TDEGlobal::locale()->readNumber(s, &res);
if (ok) *ok = res;
if (res) {
return Duration((TQ_INT64)(f*3600.0));
}
break;
}
default:
kdFatal()<<k_funcinfo<<"Unknown format"<<endl;
break;
}
return tmp;
}
void Duration::get(unsigned *days, unsigned *hours, unsigned *minutes, unsigned *seconds, unsigned *milliseconds) const {
TQ_INT64 ms;
TQ_INT64 tmp;
ms = m_ms;
tmp = ms / (1000 * 60 * 60 * 24);
*days = tmp;
ms -= tmp * (1000 * 60 * 60 * 24);
tmp = ms / (1000 * 60 * 60);
*hours = tmp;
ms -= tmp * (1000 * 60 * 60);
tmp = ms / (1000 * 60);
*minutes = tmp;
ms -= tmp * (1000 * 60);
tmp = ms / (1000);
if (seconds)
*seconds = tmp;
ms -= tmp * (1000);
if (milliseconds)
*milliseconds = ms;
}
} //KPlato namespace