00001 #include "duration.h"
00002 
00003 #include <tools/invaliddataexception.h>
00004 
00005 #include <limits.h>
00006 #include <QStringList>
00007 #include <QDateTime>
00008 
00009 namespace domain
00010 {
00011 
00017 enum
00018 {
00019     DAYS_PER_WEEK = 7,
00020     HOURS_PER_DAY = 24,
00021     MINUTES_PER_HOUR = 60,
00022     SECONDS_PER_MINUTE = 60,
00023     SECONDS_PER_HOUR = MINUTES_PER_HOUR * SECONDS_PER_MINUTE,
00024     SECONDS_PER_DAY = SECONDS_PER_HOUR * HOURS_PER_DAY,
00025     SECONDS_PER_WEEK = DAYS_PER_WEEK * SECONDS_PER_DAY
00026 };
00027 
00028 
00029 Duration::Duration(int seconds)
00030 {
00031     if (seconds > 0)
00032     {
00033         secs = seconds;
00034     }
00035     else
00036     {
00037         throw tools::InvalidDataException("Duration cannot be zero or negative.");
00038     }
00039 }
00040 
00041 Duration::Duration(int weeks, int days, int hours, int minutes, int seconds)
00042 {
00043     QStringList errorList;
00044     if (!(weeks < INT_MAX / SECONDS_PER_WEEK))
00045         errorList << "weeks";
00046     if (!(days >= 0 && days < DAYS_PER_WEEK))
00047         errorList << "days";
00048     if (!(hours >= 0 && hours < HOURS_PER_DAY))
00049         errorList << "hours";
00050     if (!(minutes >= 0 && minutes < MINUTES_PER_HOUR))
00051         errorList << "minutes";
00052     if (!(seconds >= 0 && seconds < SECONDS_PER_MINUTE))
00053         errorList << "seconds";
00054 
00055     if (errorList.isEmpty())
00056     {
00057         secs = seconds +
00058                minutes * SECONDS_PER_MINUTE +
00059                hours * SECONDS_PER_HOUR +
00060                days * SECONDS_PER_DAY +
00061                weeks * SECONDS_PER_WEEK;
00062 
00063         if (secs <= 0)
00064             throw tools::InvalidDataException("Duration cannot be zero or negative.");
00065     }
00066     else
00067     {
00068         QString message = "The following values are invalid: ";
00069         throw tools::InvalidDataException(message + errorList.join(", ") + ".");
00070     }
00071 }
00072 
00073 int Duration::weeks() const
00074 {
00075     return secs / SECONDS_PER_WEEK;
00076 }
00077 
00078 int Duration::days() const
00079 {
00080     return (secs - weeks() * SECONDS_PER_WEEK) / SECONDS_PER_DAY;
00081 }
00082 
00083 int Duration::hours() const
00084 {
00085     return (secs - weeks() * SECONDS_PER_WEEK - days() * SECONDS_PER_DAY) /
00086             SECONDS_PER_HOUR;
00087 }
00088 
00089 int Duration::minutes() const
00090 {
00091     return (secs - weeks() * SECONDS_PER_WEEK - days() * SECONDS_PER_DAY -
00092             hours() * SECONDS_PER_HOUR) / SECONDS_PER_MINUTE;
00093 }
00094 
00095 int Duration::seconds() const
00096 {
00097     return secs % SECONDS_PER_MINUTE;
00098 }
00099 
00100 int Duration::totalSeconds() const
00101 {
00102     return secs;
00103 }
00104 
00105 QString Duration::toString() const
00106 {
00107     QStringList list;
00108 
00109     if (weeks() != 0)
00110         list << QString("%1 weeks").arg(weeks());
00111     if (this->days() != 0)
00112         list << QString("%1 days").arg(days());
00113     if (this->hours() != 0)
00114         list << QString("%1 hours").arg(hours());
00115     if (this->minutes() != 0)
00116         list << QString("%1 minutes").arg(minutes());
00117     if (list.isEmpty() || seconds() != 0)
00118         list << QString("%1 seconds").arg(seconds());
00119 
00120     return list.join(", ");
00121 }
00122 
00123 bool Duration::operator==(const Duration& other) const
00124 {
00125     return secs == other.secs;
00126 }
00127 
00128 bool Duration::operator<(const Duration& other) const
00129 {
00130     return secs < other.secs;
00131 }
00132 
00133 bool Duration::operator>(const Duration& other) const
00134 {
00135     return secs > other.secs;
00136 }
00137 
00138 }
00139 
00140 QDateTime operator+(const QDateTime& left, const domain::Duration& right)
00141 {
00142     return left.addSecs(right.totalSeconds());
00143 }