Working in C++ and I have some code which I'm refactoring. I have some code that needs to work with times of day but not dates. I do some juggling with time_t
and struct tm
but it's a pain and not intuitive to use. So I decided to make a basic time class with no date component. Let me know if you see any issues or have ideas for improvement:
TimeOnly.h
#pragma once
class TimeOnly
{
public:
TimeOnly(int hour, int minute, int second);
virtual ~TimeOnly();
static TimeOnly GetCurrentTime();
virtual int GetHour() const;
virtual int GetMinute() const;
virtual int GetSecond() const;
private:
int hour_;
int minute_;
int second_;
};
inline bool operator==(const TimeOnly& lhs, const TimeOnly& rhs)
{
/* do actual comparison */
return (
(lhs.GetHour() == rhs.GetHour())
&& (lhs.GetMinute() == rhs.GetMinute())
&& (lhs.GetSecond() == rhs.GetSecond())
);
}
inline bool operator!=(const TimeOnly& lhs, const TimeOnly& rhs){ return !operator==(lhs, rhs); }
inline bool operator<(const TimeOnly& lhs, const TimeOnly& rhs)
{
/* do actual comparison */
if(lhs.GetHour() >= rhs.GetHour())
{
return false;
}
else if(lhs.GetMinute() >= rhs.GetMinute())
{
return false;
}
else if(lhs.GetSecond() >= rhs.GetSecond())
{
return false;
}
else
{
return true;
}
}
inline bool operator>(const TimeOnly& lhs, const TimeOnly& rhs){ return operator<(rhs, lhs); }
inline bool operator<=(const TimeOnly& lhs, const TimeOnly& rhs){ return !operator>(lhs, rhs); }
inline bool operator>=(const TimeOnly& lhs, const TimeOnly& rhs){ return !operator<(lhs, rhs); }
TimeOnly.cpp
#include "TimeOnly.h"
#include <stdexcept>
#include <ctime>
TimeOnly::TimeOnly(int hour, int minute, int second):
hour_(hour),
minute_(minute),
second_(second)
{
if(
(hour_ >= 0 && hour_ <= 23)
&& (minute_ >= 0 && minute_ <= 59)
&& (second_ >= 0 && second_ <= 59)
)
{
//ok
}
else
{
throw std::invalid_argument("Time must be between 0:00:00 and 23:59:59");
}
}
TimeOnly TimeOnly::GetCurrentTime()
{
// get time now
time_t t = time(0);
struct tm * now = localtime(&t);
return TimeOnly(now->tm_hour, now->tm_min, now->tm_sec);
}
TimeOnly::~TimeOnly()
{
}
int TimeOnly::GetHour() const
{
return hour_;
}
int TimeOnly::GetMinute() const
{
return minute_;
}
int TimeOnly::GetSecond() const
{
return second_;
}
Edit
This is my revised class taking some suggestions from the answers:
Time.h
#pragma once
class TimeOnly
{
public:
TimeOnly(int seconds);
TimeOnly(int hour, int minute, int second);
~TimeOnly();
TimeOnly AddSeconds(int seconds);
static TimeOnly Now();
int GetHour() const;
int GetMinute() const;
int GetSecond() const;
int GetTotalSeconds() const;
private:
void Init(int seconds);
int secondsInDay_;
static const int SECONDS_IN_A_DAY = 86400;
static const int SECONDS_IN_AN_HOUR = 3600;
static const int SECONDS_IN_A_MINUTE = 60;
};
inline bool operator==(const TimeOnly& lhs, const TimeOnly& rhs)
{
/* do actual comparison */
return lhs.GetTotalSeconds() == rhs.GetTotalSeconds();
}
inline bool operator!=(const TimeOnly& lhs, const TimeOnly& rhs){ return !operator==(lhs, rhs); }
inline bool operator<(const TimeOnly& lhs, const TimeOnly& rhs)
{
/* do actual comparison */
return lhs.GetTotalSeconds() < rhs.GetTotalSeconds();
}
inline bool operator>(const TimeOnly& lhs, const TimeOnly& rhs){ return operator<(rhs, lhs); }
inline bool operator<=(const TimeOnly& lhs, const TimeOnly& rhs){ return !operator>(lhs, rhs); }
inline bool operator>=(const TimeOnly& lhs, const TimeOnly& rhs){ return !operator<(lhs, rhs); }
TimeOnly.cpp
#include "TimeOnly.h"
#include <stdexcept>
#include <ctime>
TimeOnly::TimeOnly(int seconds)
{
Init(seconds);
}
TimeOnly::TimeOnly(int hour, int minute, int second)
{
int seconds = (hour * SECONDS_IN_AN_HOUR) + (minute * SECONDS_IN_A_MINUTE) + seconds;
Init(seconds);
}
TimeOnly::~TimeOnly()
{
}
void TimeOnly::Init(int seconds)
{
if(seconds >= 0 && seconds < SECONDS_IN_A_DAY)
{
secondsInDay_ = seconds;
}
else
{
throw std::invalid_argument("Time must be between 0:00:00 and 23:59:59");
}
}
TimeOnly TimeOnly::AddSeconds(int seconds)
{
int newSeconds = (secondsInDay_ + seconds) % SECONDS_IN_A_DAY;
return TimeOnly(newSeconds);
}
TimeOnly TimeOnly::Now()
{
// get time now
time_t t = time(0);
struct tm * now = localtime( & t );
return TimeOnly(now->tm_hour, now->tm_min, now->tm_sec);
}
int TimeOnly::GetHour() const
{
return secondsInDay_ / SECONDS_IN_AN_HOUR;
}
int TimeOnly::GetMinute() const
{
return (secondsInDay_ % (SECONDS_IN_AN_HOUR)) / SECONDS_IN_A_MINUTE;
}
int TimeOnly::GetSecond() const
{
return secondsInDay_ % SECONDS_IN_A_MINUTE;
}
int TimeOnly::GetTotalSeconds() const
{
return secondsInDay_;
}
(Note renamed GetCurrentTime()
to Now()
because I was getting error LNK2001: unresolved external symbol... GetTickCount(void)
even though I have no GetTickCount
method. Turns out winbase.h has #define GetCurrentTime() GetTickCount()
)