mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
From: Paul Beckingham <paul@beckingham.net>
Date: Sun, 28 Feb 2010 12:10:06 -0500 Subject: [PATCH] Enhancement - time support in the Date object. - Added ability to parse and display time, using: h - single digit hour H - double digit hour N - double digit minutes S - double digit seconds - Added a request for mktime() to automatically determine whether summer time should be considered. - Added Date::Date (m, d, y, hr, mi, se) constructor. - Added Date::sameHour comparison method. - Added unit tests.
This commit is contained in:
parent
dbf8def7db
commit
70da455f1a
3 changed files with 167 additions and 11 deletions
135
src/Date.cpp
135
src/Date.cpp
|
@ -55,9 +55,27 @@ Date::Date (const int m, const int d, const int y)
|
|||
{
|
||||
// Error if not valid.
|
||||
struct tm t = {0};
|
||||
t.tm_mday = d;
|
||||
t.tm_mon = m - 1;
|
||||
t.tm_year = y - 1900;
|
||||
t.tm_isdst = -1; // Requests that mktime determine summer time effect.
|
||||
t.tm_mday = d;
|
||||
t.tm_mon = m - 1;
|
||||
t.tm_year = y - 1900;
|
||||
|
||||
mT = mktime (&t);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Date::Date (const int m, const int d, const int y,
|
||||
const int hr, const int mi, const int se)
|
||||
{
|
||||
// Error if not valid.
|
||||
struct tm t = {0};
|
||||
t.tm_isdst = -1; // Requests that mktime determine summer time effect.
|
||||
t.tm_mday = d;
|
||||
t.tm_mon = m - 1;
|
||||
t.tm_year = y - 1900;
|
||||
t.tm_hour = hr;
|
||||
t.tm_min = mi;
|
||||
t.tm_sec = se;
|
||||
|
||||
mT = mktime (&t);
|
||||
}
|
||||
|
@ -65,9 +83,12 @@ Date::Date (const int m, const int d, const int y)
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
Date::Date (const std::string& mdy, const std::string& format /* = "m/d/Y" */)
|
||||
{
|
||||
int month = 0;
|
||||
int day = 0;
|
||||
int year = 0;
|
||||
int month = 0;
|
||||
int day = 0;
|
||||
int year = 0;
|
||||
int hour = 0;
|
||||
int minute = 0;
|
||||
int second = 0;
|
||||
|
||||
// Perhaps it is an epoch date, in string form?
|
||||
if (isEpoch (mdy))
|
||||
|
@ -241,6 +262,64 @@ Date::Date (const std::string& mdy, const std::string& format /* = "m/d/Y" */)
|
|||
i += Date::monthName(month).size();
|
||||
break;
|
||||
|
||||
// Single or double digit.
|
||||
case 'h':
|
||||
if (i >= mdy.length () ||
|
||||
! isdigit (mdy[i]))
|
||||
{
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date (h).";
|
||||
}
|
||||
|
||||
if (i + 1 < mdy.length () &&
|
||||
(mdy[i + 0] == '0' || mdy[i + 0] == '1' || mdy[i + 0] == '2') &&
|
||||
isdigit (mdy[i + 1]))
|
||||
{
|
||||
hour = atoi (mdy.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
hour = atoi (mdy.substr (i, 1).c_str ());
|
||||
++i;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
if (i + 1 >= mdy.length () ||
|
||||
! isdigit (mdy[i + 0]) ||
|
||||
! isdigit (mdy[i + 1]))
|
||||
{
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date (H).";
|
||||
}
|
||||
|
||||
hour = atoi (mdy.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
if (i + 1 >= mdy.length () ||
|
||||
! isdigit (mdy[i + 0]) ||
|
||||
! isdigit (mdy[i + 1]))
|
||||
{
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date (N).";
|
||||
}
|
||||
|
||||
minute = atoi (mdy.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
if (i + 1 >= mdy.length () ||
|
||||
! isdigit (mdy[i + 0]) ||
|
||||
! isdigit (mdy[i + 1]))
|
||||
{
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date (S).";
|
||||
}
|
||||
|
||||
second = atoi (mdy.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (i >= mdy.length () ||
|
||||
mdy[i] != format[f])
|
||||
|
@ -258,11 +337,15 @@ Date::Date (const std::string& mdy, const std::string& format /* = "m/d/Y" */)
|
|||
if (!valid (month, day, year))
|
||||
throw std::string ("\"") + mdy + "\" is not a valid date (VALID).";
|
||||
|
||||
// Duplicate Date::Date (const int, const int, const int);
|
||||
// Convert to epoch.
|
||||
struct tm t = {0};
|
||||
t.tm_mday = day;
|
||||
t.tm_mon = month - 1;
|
||||
t.tm_year = year - 1900;
|
||||
t.tm_isdst = -1; // Requests that mktime determine summer time effect.
|
||||
t.tm_mday = day;
|
||||
t.tm_mon = month - 1;
|
||||
t.tm_year = year - 1900;
|
||||
t.tm_hour = hour;
|
||||
t.tm_min = minute;
|
||||
t.tm_sec = second;
|
||||
|
||||
mT = mktime (&t);
|
||||
}
|
||||
|
@ -333,6 +416,10 @@ const std::string Date::toString (const std::string& format /*= "m/d/Y" */) cons
|
|||
case 'b': sprintf (buffer, "%.3s", Date::monthName (month ()).c_str ()); break;
|
||||
case 'B': sprintf (buffer, "%.9s", Date::monthName (month ()).c_str ()); break;
|
||||
case 'V': sprintf (buffer, "%02d", Date::weekOfYear (Date::dayOfWeek (context.config.get ("weekstart")))); break;
|
||||
case 'h': sprintf (buffer, "%d", this->hour ()); break;
|
||||
case 'H': sprintf (buffer, "%02d", this->hour ()); break;
|
||||
case 'N': sprintf (buffer, "%02d", this->minute ()); break;
|
||||
case 'S': sprintf (buffer, "%02d", this->second ()); break;
|
||||
default: sprintf (buffer, "%c", c); break;
|
||||
}
|
||||
|
||||
|
@ -371,6 +458,22 @@ bool Date::valid (const std::string& input, const std::string& format)
|
|||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Date::valid (const int m, const int d, const int y, const int hr,
|
||||
const int mi, const int se)
|
||||
{
|
||||
if (hr < 0 || hr > 23)
|
||||
return false;
|
||||
|
||||
if (mi < 0 || mi > 59)
|
||||
return false;
|
||||
|
||||
if (se < 0 || se > 59)
|
||||
return false;
|
||||
|
||||
return Date::valid (m, d, y);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Date::valid (const int m, const int d, const int y)
|
||||
{
|
||||
|
@ -618,6 +721,18 @@ bool Date::operator>= (const Date& rhs)
|
|||
return mT >= rhs.mT;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Date::sameHour (const Date& rhs)
|
||||
{
|
||||
if (this->year () == rhs.year () &&
|
||||
this->month () == rhs.month () &&
|
||||
this->day () == rhs.day () &&
|
||||
this->hour () == rhs.hour ())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Date::sameDay (const Date& rhs)
|
||||
{
|
||||
|
|
|
@ -38,6 +38,7 @@ public:
|
|||
Date ();
|
||||
Date (time_t);
|
||||
Date (const int, const int, const int);
|
||||
Date (const int, const int, const int, const int, const int, const int);
|
||||
Date (const std::string&, const std::string& format = "m/d/Y");
|
||||
Date (const Date&);
|
||||
virtual ~Date ();
|
||||
|
@ -49,6 +50,7 @@ public:
|
|||
const std::string toString (const std::string& format = "m/d/Y") const;
|
||||
const std::string toStringWithTime (const std::string& format = "m/d/Y") const;
|
||||
static bool valid (const std::string&, const std::string& format = "m/d/Y");
|
||||
static bool valid (const int, const int, const int, const int, const int, const int);
|
||||
static bool valid (const int, const int, const int);
|
||||
|
||||
static bool leapYear (int);
|
||||
|
@ -75,6 +77,7 @@ public:
|
|||
bool operator> (const Date&);
|
||||
bool operator<= (const Date&);
|
||||
bool operator>= (const Date&);
|
||||
bool sameHour (const Date&);
|
||||
bool sameDay (const Date&);
|
||||
bool sameMonth (const Date&);
|
||||
bool sameYear (const Date&);
|
||||
|
|
|
@ -34,7 +34,7 @@ Context context;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
UnitTest t (111);
|
||||
UnitTest t (135);
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -78,6 +78,12 @@ int main (int argc, char** argv)
|
|||
t.ok (Date::valid ("2/29/2008"), "valid: 2/29/2008");
|
||||
t.notok (Date::valid ("2/29/2007"), "invalid: 2/29/2007");
|
||||
|
||||
// Time validity.
|
||||
t.ok (Date::valid (2, 28, 2010, 0, 0, 0), "valid 2/28/2010 0:00:00");
|
||||
t.ok (Date::valid (2, 28, 2010, 23, 59, 59), "valid 2/28/2010 23:59:59");
|
||||
t.notok (Date::valid (2, 28, 2010, 24, 59, 59), "valid 2/28/2010 24:59:59");
|
||||
t.notok (Date::valid (2, 28, 2010, -1, 0, 0), "valid 2/28/2010 -1:00:00");
|
||||
|
||||
// Leap year.
|
||||
t.ok (Date::leapYear (2008), "2008 is a leap year");
|
||||
t.notok (Date::leapYear (2007), "2007 is not a leap year");
|
||||
|
@ -195,6 +201,30 @@ int main (int argc, char** argv)
|
|||
t.is (fromString10.day (), 1, "ctor (std::string) -> d");
|
||||
t.is (fromString10.year (), 2008, "ctor (std::string) -> y");
|
||||
|
||||
Date fromString11 ("6/7/2010 1:23:45", "m/d/Y h:N:S");
|
||||
t.is (fromString11.month (), 6, "ctor (std::string) -> m");
|
||||
t.is (fromString11.day (), 7, "ctor (std::string) -> d");
|
||||
t.is (fromString11.year (), 2010, "ctor (std::string) -> Y");
|
||||
t.is (fromString11.hour (), 1, "ctor (std::string) -> h");
|
||||
t.is (fromString11.minute (), 23, "ctor (std::string) -> N");
|
||||
t.is (fromString11.second (), 45, "ctor (std::string) -> S");
|
||||
|
||||
Date fromString12 ("6/7/2010 01:23:45", "m/d/Y H:N:S");
|
||||
t.is (fromString12.month (), 6, "ctor (std::string) -> m");
|
||||
t.is (fromString12.day (), 7, "ctor (std::string) -> d");
|
||||
t.is (fromString12.year (), 2010, "ctor (std::string) -> Y");
|
||||
t.is (fromString12.hour (), 1, "ctor (std::string) -> h");
|
||||
t.is (fromString12.minute (), 23, "ctor (std::string) -> N");
|
||||
t.is (fromString12.second (), 45, "ctor (std::string) -> S");
|
||||
|
||||
Date fromString13 ("6/7/2010 12:34:56", "m/d/Y H:N:S");
|
||||
t.is (fromString13.month (), 6, "ctor (std::string) -> m");
|
||||
t.is (fromString13.day (), 7, "ctor (std::string) -> d");
|
||||
t.is (fromString13.year (), 2010, "ctor (std::string) -> Y");
|
||||
t.is (fromString13.hour (), 12, "ctor (std::string) -> h");
|
||||
t.is (fromString13.minute (), 34, "ctor (std::string) -> N");
|
||||
t.is (fromString13.second (), 56, "ctor (std::string) -> S");
|
||||
|
||||
// Relative dates.
|
||||
Date r1 ("today");
|
||||
t.ok (r1.sameDay (now), "today = now");
|
||||
|
@ -255,6 +285,14 @@ int main (int argc, char** argv)
|
|||
|
||||
Date r13 ("eoy");
|
||||
t.ok (r13.sameYear (now), "eoy in same year as now");
|
||||
|
||||
// Date::sameHour
|
||||
Date r14 ("6/7/2010 01:00:00", "m/d/Y H:N:S");
|
||||
Date r15 ("6/7/2010 01:59:59", "m/d/Y H:N:S");
|
||||
t.ok (r14.sameHour (r15), "two dates within the same hour");
|
||||
|
||||
Date r16 ("6/7/2010 00:59:59", "m/d/Y H:N:S");
|
||||
t.notok (r14.sameHour (r16), "two dates not within the same hour");
|
||||
}
|
||||
|
||||
catch (std::string& e)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue