Merge branch 'isodate' into 2.5.0

This commit is contained in:
Paul Beckingham 2015-10-07 07:40:28 -04:00
commit 79886e03ce
42 changed files with 1916 additions and 1898 deletions

View file

@ -10,7 +10,6 @@ set (task_SRCS CLI2.cpp CLI2.h
Config.cpp Config.h Config.cpp Config.h
Context.cpp Context.h Context.cpp Context.h
DOM.cpp DOM.h DOM.cpp DOM.h
Date.cpp Date.h
Dates.cpp Dates.h Dates.cpp Dates.h
Eval.cpp Eval.h Eval.cpp Eval.h
Filter.cpp Filter.h Filter.cpp Filter.h

View file

@ -33,7 +33,7 @@
#include <inttypes.h> #include <inttypes.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <Date.h> #include <ISO8601.h>
#include <FS.h> #include <FS.h>
#include <Timer.h> #include <Timer.h>
#include <JSON.h> #include <JSON.h>
@ -574,7 +574,7 @@ void Config::createDefaultRC (const std::string& rc, const std::string& data)
auto loc = _defaults.find ("data.location=~/.task"); auto loc = _defaults.find ("data.location=~/.task");
// loc+0^ +14^ +21^ // loc+0^ +14^ +21^
Date now; ISO8601d now;
std::stringstream contents; std::stringstream contents;
contents << "# [Created by " contents << "# [Created by "
<< PACKAGE_STRING << PACKAGE_STRING

View file

@ -37,6 +37,7 @@
#include <FS.h> #include <FS.h>
#include <Eval.h> #include <Eval.h>
#include <Variant.h> #include <Variant.h>
#include <ISO8601.h>
#include <text.h> #include <text.h>
#include <util.h> #include <util.h>
#include <main.h> #include <main.h>
@ -328,7 +329,7 @@ int Context::run ()
<< "-" << "-"
#endif #endif
<< " " << " "
<< Date ().toISO () << ISO8601d ().toISO ()
<< " init:" << timer_init.total () << " init:" << timer_init.total ()
<< " load:" << timer_load.total () << " load:" << timer_load.total ()
@ -623,6 +624,7 @@ void Context::staticInitialization ()
{ {
CLI2::minimumMatchLength = config.getInteger ("abbreviation.minimum"); CLI2::minimumMatchLength = config.getInteger ("abbreviation.minimum");
Lexer::minimumMatchLength = config.getInteger ("abbreviation.minimum"); Lexer::minimumMatchLength = config.getInteger ("abbreviation.minimum");
ISO8601d::minimumMatchLength = config.getInteger ("abbreviation.minimum");
Task::defaultProject = config.get ("default.project"); Task::defaultProject = config.get ("default.project");
Task::defaultDue = config.get ("default.due"); Task::defaultDue = config.get ("default.due");
@ -630,10 +632,12 @@ void Context::staticInitialization ()
Task::searchCaseSensitive = Variant::searchCaseSensitive = config.getBoolean ("search.case.sensitive"); Task::searchCaseSensitive = Variant::searchCaseSensitive = config.getBoolean ("search.case.sensitive");
Task::regex = Variant::searchUsingRegex = config.getBoolean ("regex"); Task::regex = Variant::searchUsingRegex = config.getBoolean ("regex");
Lexer::dateFormat = Variant::dateFormat = config.get ("dateformat"); Lexer::dateFormat = Variant::dateFormat = config.get ("dateformat");
Lexer::isoEnabled = Variant::isoEnabled = config.getBoolean ("date.iso"); ISO8601p::isoEnabled = ISO8601d::isoEnabled = config.getBoolean ("date.iso");
TDB2::debug_mode = config.getBoolean ("debug"); TDB2::debug_mode = config.getBoolean ("debug");
ISO8601d::weekstart = config.get ("weekstart");
for (auto& rc : config) for (auto& rc : config)
{ {
if (rc.first.substr (0, 4) == "uda." && if (rc.first.substr (0, 4) == "uda." &&

View file

@ -32,7 +32,6 @@
#include <Context.h> #include <Context.h>
#include <Nibbler.h> #include <Nibbler.h>
#include <ISO8601.h> #include <ISO8601.h>
#include <Date.h>
#include <text.h> #include <text.h>
#include <i18n.h> #include <i18n.h>
#include <DOM.h> #include <DOM.h>
@ -300,7 +299,7 @@ bool DOM::get (const std::string& name, const Task& task, Variant& value)
ISO8601p iso; ISO8601p iso;
std::string::size_type cursor = 0; std::string::size_type cursor = 0;
if (iso.parse (period, cursor)) if (iso.parse (period, cursor))
value = Variant ((time_t) iso._value, Variant::type_duration); value = Variant ((time_t) iso, Variant::type_duration);
else else
value = Variant ((time_t) ISO8601p (ref.get (canonical)), Variant::type_duration); value = Variant ((time_t) ISO8601p (ref.get (canonical)), Variant::type_duration);
} }
@ -320,7 +319,7 @@ bool DOM::get (const std::string& name, const Task& task, Variant& value)
if (ref.size () && size == 2 && column && column->type () == "date") if (ref.size () && size == 2 && column && column->type () == "date")
{ {
Date date (ref.get_date (canonical)); ISO8601d date (ref.get_date (canonical));
if (elements[1] == "year") { value = Variant (static_cast<int> (date.year ())); return true; } if (elements[1] == "year") { value = Variant (static_cast<int> (date.year ())); return true; }
else if (elements[1] == "month") { value = Variant (static_cast<int> (date.month ())); return true; } else if (elements[1] == "month") { value = Variant (static_cast<int> (date.month ())); return true; }
else if (elements[1] == "day") { value = Variant (static_cast<int> (date.day ())); return true; } else if (elements[1] == "day") { value = Variant (static_cast<int> (date.day ())); return true; }
@ -384,7 +383,7 @@ bool DOM::get (const std::string& name, const Task& task, Variant& value)
// <annotations>.<N>.entry.hour // <annotations>.<N>.entry.hour
// <annotations>.<N>.entry.minute // <annotations>.<N>.entry.minute
// <annotations>.<N>.entry.second // <annotations>.<N>.entry.second
Date date (i.first.substr (11)); ISO8601d date (i.first.substr (11));
if (elements[3] == "year") { value = Variant (static_cast<int> (date.year ())); return true; } if (elements[3] == "year") { value = Variant (static_cast<int> (date.year ())); return true; }
else if (elements[3] == "month") { value = Variant (static_cast<int> (date.month ())); return true; } else if (elements[3] == "month") { value = Variant (static_cast<int> (date.month ())); return true; }
else if (elements[3] == "day") { value = Variant (static_cast<int> (date.day ())); return true; } else if (elements[3] == "day") { value = Variant (static_cast<int> (date.day ())); return true; }

View file

@ -1,839 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////
#include <cmake.h>
#include <iomanip>
#include <sstream>
#include <time.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <Nibbler.h>
#include <Date.h>
#include <Variant.h>
#include <Dates.h>
#include <text.h>
#include <util.h>
#include <utf8.h>
#include <i18n.h>
#include <Context.h>
extern Context context;
////////////////////////////////////////////////////////////////////////////////
// Defaults to "now".
Date::Date ()
{
_t = time (NULL);
}
////////////////////////////////////////////////////////////////////////////////
Date::Date (const time_t t)
{
_t = t;
}
////////////////////////////////////////////////////////////////////////////////
Date::Date (const int m, const int d, const int y)
{
// 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 = 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;
_t = mktime (&t);
}
////////////////////////////////////////////////////////////////////////////////
Date::Date (
const std::string& input,
const std::string& format /* = "m/d/Y" */,
const bool iso /* = true */,
const bool epoch /* = true */)
{
// Check first to see if this is supported as a named date.
Variant v;
if (namedDates (input, v))
{
_t = v.get_date ();
return;
}
// Parse a formatted date.
Nibbler n (input);
n.save ();
#ifdef NIBBLER_FEATURE_DATE
if (n.getDate (format, _t) && n.depleted ())
return;
#endif
// Parse an ISO date.
n.restore ();
if (iso && n.getDateISO (_t) && n.depleted ())
return;
// Perhaps it is an epoch date, in string form?
n.restore ();
if (epoch && isEpoch (input))
return;
throw ::format (STRING_DATE_INVALID_FORMAT, input, format);
}
////////////////////////////////////////////////////////////////////////////////
Date::Date (
const std::string& input,
std::string::size_type& i,
const std::string& format /* = "m/d/Y" */,
const bool iso /* = true */,
const bool epoch /* = true */)
{
// Check first to see if this is supported as a named date.
Variant v;
if (namedDates (input, v))
{
i = v.source ().length ();
_t = v.get_date ();
return;
}
// Parse a formatted date.
Nibbler n (input);
n.save ();
#ifdef NIBBLER_FEATURE_DATE
if (n.getDate (format, _t))
{
i = n.cursor ();
return;
}
#endif
// Parse an ISO date.
n.restore ();
if (iso && n.getDateISO (_t))
{
i = n.cursor ();
return;
}
// Perhaps it is an epoch date, in string form?
n.restore ();
if (epoch && isEpoch (input))
{
i = 10;
return;
}
throw ::format (STRING_DATE_INVALID_FORMAT, input, format);
}
////////////////////////////////////////////////////////////////////////////////
Date::Date (const Date& rhs)
{
_t = rhs._t;
}
////////////////////////////////////////////////////////////////////////////////
Date::~Date ()
{
}
////////////////////////////////////////////////////////////////////////////////
time_t Date::toEpoch ()
{
return _t;
}
////////////////////////////////////////////////////////////////////////////////
std::string Date::toEpochString ()
{
std::stringstream epoch;
epoch << _t;
return epoch.str ();
}
////////////////////////////////////////////////////////////////////////////////
// 19980119T070000Z = YYYYMMDDThhmmssZ
std::string Date::toISO ()
{
struct tm* t = gmtime (&_t);
std::stringstream iso;
iso << std::setw (4) << std::setfill ('0') << t->tm_year + 1900
<< std::setw (2) << std::setfill ('0') << t->tm_mon + 1
<< std::setw (2) << std::setfill ('0') << t->tm_mday
<< "T"
<< std::setw (2) << std::setfill ('0') << t->tm_hour
<< std::setw (2) << std::setfill ('0') << t->tm_min
<< std::setw (2) << std::setfill ('0') << t->tm_sec
<< "Z";
return iso.str ();
}
////////////////////////////////////////////////////////////////////////////////
double Date::toJulian ()
{
return (_t / 86400.0) + 2440587.5;
}
////////////////////////////////////////////////////////////////////////////////
void Date::toEpoch (time_t& epoch)
{
epoch = _t;
}
////////////////////////////////////////////////////////////////////////////////
void Date::toMDY (int& m, int& d, int& y)
{
struct tm* t = localtime (&_t);
m = t->tm_mon + 1;
d = t->tm_mday;
y = t->tm_year + 1900;
}
////////////////////////////////////////////////////////////////////////////////
const std::string Date::toString (
const std::string& format /*= "m/d/Y" */) const
{
// Making this local copy seems to fix a bug. Remove the local copy and
// you'll see segmentation faults and all kinds of gibberish.
std::string localFormat = format;
char buffer[12];
std::string formatted;
for (unsigned int i = 0; i < localFormat.length (); ++i)
{
int c = localFormat[i];
switch (c)
{
case 'm': sprintf (buffer, "%d", this->month ()); break;
case 'M': sprintf (buffer, "%02d", this->month ()); break;
case 'd': sprintf (buffer, "%d", this->day ()); break;
case 'D': sprintf (buffer, "%02d", this->day ()); break;
case 'y': sprintf (buffer, "%02d", this->year () % 100); break;
case 'Y': sprintf (buffer, "%d", this->year ()); break;
case 'a': sprintf (buffer, "%.3s", Date::dayName (dayOfWeek ()).c_str ()); break;
case 'A': sprintf (buffer, "%.10s", Date::dayName (dayOfWeek ()).c_str ()); break;
case 'b': sprintf (buffer, "%.3s", Date::monthName (month ()).c_str ()); break;
case 'B': sprintf (buffer, "%.10s", Date::monthName (month ()).c_str ()); break;
case 'v': sprintf (buffer, "%d", Date::weekOfYear (Date::dayOfWeek (context.config.get ("weekstart")))); 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, "%d", this->minute ()); break;
case 'N': sprintf (buffer, "%02d", this->minute ()); break;
case 's': sprintf (buffer, "%d", this->second ()); break;
case 'S': sprintf (buffer, "%02d", this->second ()); break;
case 'j': sprintf (buffer, "%d", this->dayOfYear ()); break;
case 'J': sprintf (buffer, "%03d", this->dayOfYear ()); break;
default: sprintf (buffer, "%c", c); break;
}
formatted += buffer;
}
return formatted;
}
////////////////////////////////////////////////////////////////////////////////
Date Date::startOfDay () const
{
return Date (month (), day (), year ());
}
////////////////////////////////////////////////////////////////////////////////
Date Date::startOfWeek () const
{
Date sow (_t);
sow -= (dayOfWeek () * 86400);
return Date (sow.month (), sow.day (), sow.year ());
}
////////////////////////////////////////////////////////////////////////////////
Date Date::startOfMonth () const
{
return Date (month (), 1, year ());
}
////////////////////////////////////////////////////////////////////////////////
Date Date::startOfYear () const
{
return Date (1, 1, year ());
}
////////////////////////////////////////////////////////////////////////////////
bool Date::valid (const std::string& input, const std::string& format)
{
try
{
Date test (input, format);
}
catch (...)
{
return false;
}
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)
{
// Check that the year is valid.
if (y < 0)
return false;
// Check that the month is valid.
if (m < 1 || m > 12)
return false;
// Finally check that the days fall within the acceptable range for this
// month, and whether or not this is a leap year.
if (d < 1 || d > Date::daysInMonth (m, y))
return false;
return true;
}
////////////////////////////////////////////////////////////////////////////////
// Julian
bool Date::valid (const int d, const int y)
{
// Check that the year is valid.
if (y < 0)
return false;
if (d < 1 || d > Date::daysInYear (y))
return false;
return true;
}
////////////////////////////////////////////////////////////////////////////////
bool Date::leapYear (int year)
{
bool ly = false;
// (year % 4 == 0) && (year % 100 !=0) OR
// (year % 400 == 0)
// are leapyears
if (((!(year % 4)) && (year % 100)) || (!(year % 400))) ly = true;
return ly;
}
////////////////////////////////////////////////////////////////////////////////
int Date::daysInMonth (int month, int year)
{
static int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (month == 2 && Date::leapYear (year))
return 29;
return days[month - 1];
}
////////////////////////////////////////////////////////////////////////////////
int Date::daysInYear (int year)
{
return Date::leapYear (year) ? 366 : 365;
}
////////////////////////////////////////////////////////////////////////////////
std::string Date::monthName (int month)
{
static const char* months[12] =
{
STRING_DATE_JANUARY,
STRING_DATE_FEBRUARY,
STRING_DATE_MARCH,
STRING_DATE_APRIL,
STRING_DATE_MAY,
STRING_DATE_JUNE,
STRING_DATE_JULY,
STRING_DATE_AUGUST,
STRING_DATE_SEPTEMBER,
STRING_DATE_OCTOBER,
STRING_DATE_NOVEMBER,
STRING_DATE_DECEMBER,
};
assert (month > 0);
assert (month <= 12);
return ucFirst (months[month - 1]);
}
////////////////////////////////////////////////////////////////////////////////
void Date::dayName (int dow, std::string& name)
{
static const char* days[7] =
{
STRING_DATE_SUNDAY,
STRING_DATE_MONDAY,
STRING_DATE_TUESDAY,
STRING_DATE_WEDNESDAY,
STRING_DATE_THURSDAY,
STRING_DATE_FRIDAY,
STRING_DATE_SATURDAY,
};
name = ucFirst (days[dow]);
}
////////////////////////////////////////////////////////////////////////////////
std::string Date::dayName (int dow)
{
static const char* days[7] =
{
STRING_DATE_SUNDAY,
STRING_DATE_MONDAY,
STRING_DATE_TUESDAY,
STRING_DATE_WEDNESDAY,
STRING_DATE_THURSDAY,
STRING_DATE_FRIDAY,
STRING_DATE_SATURDAY,
};
return ucFirst (days[dow]);
}
////////////////////////////////////////////////////////////////////////////////
int Date::weekOfYear (int weekStart) const
{
struct tm* t = localtime (&_t);
char weekStr[3];
if (weekStart == 0)
strftime(weekStr, sizeof(weekStr), "%U", t);
else if (weekStart == 1)
strftime(weekStr, sizeof(weekStr), "%V", t);
else
throw std::string (STRING_DATE_BAD_WEEKSTART);
int weekNumber = atoi (weekStr);
if (weekStart == 0)
weekNumber += 1;
return weekNumber;
}
////////////////////////////////////////////////////////////////////////////////
int Date::dayOfWeek () const
{
struct tm* t = localtime (&_t);
return t->tm_wday;
}
////////////////////////////////////////////////////////////////////////////////
int Date::dayOfWeek (const std::string& input)
{
int minimum = CLI2::minimumMatchLength;
if (minimum == 0)
minimum = 3;
if (closeEnough (STRING_DATE_SUNDAY, input, minimum)) return 0;
else if (closeEnough (STRING_DATE_MONDAY, input, minimum)) return 1;
else if (closeEnough (STRING_DATE_TUESDAY, input, minimum)) return 2;
else if (closeEnough (STRING_DATE_WEDNESDAY, input, minimum)) return 3;
else if (closeEnough (STRING_DATE_THURSDAY, input, minimum)) return 4;
else if (closeEnough (STRING_DATE_FRIDAY, input, minimum)) return 5;
else if (closeEnough (STRING_DATE_SATURDAY, input, minimum)) return 6;
return -1;
}
////////////////////////////////////////////////////////////////////////////////
int Date::dayOfYear () const
{
struct tm* t = localtime (&_t);
return t->tm_yday + 1;
}
////////////////////////////////////////////////////////////////////////////////
int Date::monthOfYear (const std::string& input)
{
int minimum = CLI2::minimumMatchLength;
if (minimum == 0)
minimum = 3;
if (closeEnough (STRING_DATE_JANUARY, input, minimum)) return 1;
else if (closeEnough (STRING_DATE_FEBRUARY, input, minimum)) return 2;
else if (closeEnough (STRING_DATE_MARCH, input, minimum)) return 3;
else if (closeEnough (STRING_DATE_APRIL, input, minimum)) return 4;
else if (closeEnough (STRING_DATE_MAY, input, minimum)) return 5;
else if (closeEnough (STRING_DATE_JUNE, input, minimum)) return 6;
else if (closeEnough (STRING_DATE_JULY, input, minimum)) return 7;
else if (closeEnough (STRING_DATE_AUGUST, input, minimum)) return 8;
else if (closeEnough (STRING_DATE_SEPTEMBER, input, minimum)) return 9;
else if (closeEnough (STRING_DATE_OCTOBER, input, minimum)) return 10;
else if (closeEnough (STRING_DATE_NOVEMBER, input, minimum)) return 11;
else if (closeEnough (STRING_DATE_DECEMBER, input, minimum)) return 12;
return -1;
}
////////////////////////////////////////////////////////////////////////////////
int Date::length (const std::string& format)
{
int total = 0;
for (auto& i : format)
{
switch (i)
{
case 'm':
case 'M':
case 'd':
case 'D':
case 'y':
case 'v':
case 'V':
case 'h':
case 'H':
case 'n':
case 'N':
case 's':
case 'S': total += 2; break;
case 'b':
case 'j':
case 'J':
case 'a': total += 3; break;
case 'Y': total += 4; break;
case 'A':
case 'B': total += 10; break;
// Calculate the width, don't assume a single character width.
default: total += mk_wcwidth (i); break;
}
}
return total;
}
////////////////////////////////////////////////////////////////////////////////
time_t Date::easter (int year)
{
int Y = year;
int a = Y % 19;
int b = Y / 100;
int c = Y % 100;
int d = b / 4;
int e = b % 4;
int f = (b + 8) / 25;
int g = (b - f + 1) / 3;
int h = (19 * a + b - d - g + 15) % 30;
int i = c / 4;
int k = c % 4;
int L = (32 + 2 * e + 2 * i - h - k) % 7;
int m = (a + 11 * h + 22 * L) / 451;
int month = (h + L - 7 * m + 114) / 31;
int day = ((h + L - 7 * m + 114) % 31) + 1;
struct tm t = {0};
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;
return mktime (&t);
}
////////////////////////////////////////////////////////////////////////////////
int Date::month () const
{
struct tm* t = localtime (&_t);
return t->tm_mon + 1;
}
////////////////////////////////////////////////////////////////////////////////
int Date::week () const
{
return Date::weekOfYear (Date::dayOfWeek (context.config.get ("weekstart")));
}
////////////////////////////////////////////////////////////////////////////////
int Date::day () const
{
struct tm* t = localtime (&_t);
return t->tm_mday;
}
////////////////////////////////////////////////////////////////////////////////
int Date::year () const
{
struct tm* t = localtime (&_t);
return t->tm_year + 1900;
}
////////////////////////////////////////////////////////////////////////////////
int Date::hour () const
{
struct tm* t = localtime (&_t);
return t->tm_hour;
}
////////////////////////////////////////////////////////////////////////////////
int Date::minute () const
{
struct tm* t = localtime (&_t);
return t->tm_min;
}
////////////////////////////////////////////////////////////////////////////////
int Date::second () const
{
struct tm* t = localtime (&_t);
return t->tm_sec;
}
////////////////////////////////////////////////////////////////////////////////
bool Date::operator== (const Date& rhs) const
{
return rhs._t == _t;
}
////////////////////////////////////////////////////////////////////////////////
bool Date::operator!= (const Date& rhs) const
{
return rhs._t != _t;
}
////////////////////////////////////////////////////////////////////////////////
bool Date::operator< (const Date& rhs) const
{
return _t < rhs._t;
}
////////////////////////////////////////////////////////////////////////////////
bool Date::operator> (const Date& rhs) const
{
return _t > rhs._t;
}
////////////////////////////////////////////////////////////////////////////////
bool Date::operator<= (const Date& rhs) const
{
return _t <= rhs._t;
}
////////////////////////////////////////////////////////////////////////////////
bool Date::operator>= (const Date& rhs) const
{
return _t >= rhs._t;
}
////////////////////////////////////////////////////////////////////////////////
bool Date::sameHour (const Date& rhs) const
{
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) const
{
if (this->year () == rhs.year () &&
this->month () == rhs.month () &&
this->day () == rhs.day ())
return true;
return false;
}
////////////////////////////////////////////////////////////////////////////////
bool Date::sameWeek (const Date& rhs) const
{
if (this->year () == rhs.year () &&
this->week () == rhs.week ())
return true;
return false;
}
////////////////////////////////////////////////////////////////////////////////
bool Date::sameMonth (const Date& rhs) const
{
if (this->year () == rhs.year () &&
this->month () == rhs.month ())
return true;
return false;
}
////////////////////////////////////////////////////////////////////////////////
bool Date::sameYear (const Date& rhs) const
{
if (this->year () == rhs.year ())
return true;
return false;
}
////////////////////////////////////////////////////////////////////////////////
Date Date::operator- (const int delta)
{
return Date (_t - delta);
}
////////////////////////////////////////////////////////////////////////////////
Date Date::operator+ (const int delta)
{
return Date (_t + delta);
}
////////////////////////////////////////////////////////////////////////////////
Date& Date::operator+= (const int delta)
{
_t += (time_t) delta;
return *this;
}
////////////////////////////////////////////////////////////////////////////////
Date& Date::operator-= (const int delta)
{
_t -= (time_t) delta;
return *this;
}
////////////////////////////////////////////////////////////////////////////////
time_t Date::operator- (const Date& rhs)
{
return _t - rhs._t;
}
////////////////////////////////////////////////////////////////////////////////
// Prefix decrement by one day.
void Date::operator-- ()
{
Date yesterday = startOfDay () - 1;
yesterday = Date (yesterday.month (),
yesterday.day (),
yesterday.year (),
hour (),
minute (),
second ());
_t = yesterday._t;
}
////////////////////////////////////////////////////////////////////////////////
// Postfix decrement by one day.
void Date::operator-- (int)
{
Date yesterday = startOfDay () - 1;
yesterday = Date (yesterday.month (),
yesterday.day (),
yesterday.year (),
hour (),
minute (),
second ());
_t = yesterday._t;
}
////////////////////////////////////////////////////////////////////////////////
// Prefix increment by one day.
void Date::operator++ ()
{
Date tomorrow = (startOfDay () + 90001).startOfDay ();
tomorrow = Date (tomorrow.month (),
tomorrow.day (),
tomorrow.year (),
hour (),
minute (),
second ());
_t = tomorrow._t;
}
////////////////////////////////////////////////////////////////////////////////
// Postfix increment by one day.
void Date::operator++ (int)
{
Date tomorrow = (startOfDay () + 90001).startOfDay ();
tomorrow = Date (tomorrow.month (),
tomorrow.day (),
tomorrow.year (),
hour (),
minute (),
second ());
_t = tomorrow._t;
}
////////////////////////////////////////////////////////////////////////////////
bool Date::isEpoch (const std::string& input)
{
if (Lexer::isAllDigits (input) &&
input.length () <= 10 )
{
_t = (time_t) atoi (input.c_str ());
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,129 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_DATE
#define INCLUDED_DATE
#include <stdio.h>
#include <vector>
#include <string>
class Date;
class Date
{
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",
const bool iso = true,
const bool epoch = true);
Date (const std::string&,
std::string::size_type&,
const std::string& format = "m/d/Y",
const bool iso = true,
const bool epoch = true);
Date (const Date&);
virtual ~Date ();
void toEpoch (time_t&);
time_t toEpoch ();
std::string toEpochString ();
std::string toISO ();
double toJulian ();
void toMDY (int&, int&, int&);
const std::string toString (const std::string& format = "m/d/Y") const;
Date startOfDay () const;
Date startOfWeek () const;
Date startOfMonth () const;
Date startOfYear () 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 valid (const int, const int);
static time_t easter (int year);
static bool leapYear (int);
static int daysInMonth (int, int);
static int daysInYear (int);
static std::string monthName (int);
static void dayName (int, std::string&);
static std::string dayName (int);
static int weekOfYear (const std::string&);
static int dayOfWeek (const std::string&);
static int monthOfYear (const std::string&);
static int length (const std::string&);
int month () const;
int week () const;
int day () const;
int year () const;
int weekOfYear (int) const;
int dayOfWeek () const;
int dayOfYear () const;
int hour () const;
int minute () const;
int second () const;
bool operator== (const Date&) const;
bool operator!= (const Date&) const;
bool operator< (const Date&) const;
bool operator> (const Date&) const;
bool operator<= (const Date&) const;
bool operator>= (const Date&) const;
bool sameHour (const Date&) const;
bool sameDay (const Date&) const;
bool sameWeek (const Date&) const;
bool sameMonth (const Date&) const;
bool sameYear (const Date&) const;
Date operator+ (const int);
Date operator- (const int);
Date& operator+= (const int);
Date& operator-= (const int);
time_t operator- (const Date&);
void operator-- (); // Prefix
void operator-- (int); // Postfix
void operator++ (); // Prefix
void operator++ (int); // Postfix
private:
bool isEpoch (const std::string&);
protected:
time_t _t;
};
#endif
////////////////////////////////////////////////////////////////////////////////

View file

@ -30,7 +30,7 @@
#include <time.h> #include <time.h>
#include <text.h> #include <text.h>
#include <Dates.h> #include <Dates.h>
#include <Date.h> #include <ISO8601.h>
#include <Lexer.h> #include <Lexer.h>
#include <CLI2.h> #include <CLI2.h>
#include <i18n.h> #include <i18n.h>
@ -38,14 +38,14 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
static bool isMonth (const std::string& name, int& i) static bool isMonth (const std::string& name, int& i)
{ {
i = Date::monthOfYear (name) - 1; i = ISO8601d::monthOfYear (name) - 1;
return i != -2 ? true : false; return i != -2 ? true : false;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
static bool isDay (const std::string& name, int& i) static bool isDay (const std::string& name, int& i)
{ {
i = Date::dayOfWeek (name); i = ISO8601d::dayOfWeek (name);
return i != -1 ? true : false; return i != -1 ? true : false;
} }
@ -103,6 +103,7 @@ static void midsommarafton (struct tm* t)
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Note how these are all single words:
// <day> // <day>
// <month> // <month>
// Nth // Nth
@ -302,7 +303,7 @@ bool namedDates (const std::string& name, Variant& value)
t->tm_hour = 24; t->tm_hour = 24;
t->tm_min = 0; t->tm_min = 0;
t->tm_sec = -1; t->tm_sec = -1;
t->tm_mday = Date::daysInMonth (t->tm_mon + 1, t->tm_year + 1900); t->tm_mday = ISO8601d::daysInMonth (t->tm_mon + 1, t->tm_year + 1900);
t->tm_isdst = -1; t->tm_isdst = -1;
value = Variant (mktime (t), Variant::type_date); value = Variant (mktime (t), Variant::type_date);
} }
@ -414,7 +415,7 @@ bool namedDates (const std::string& name, Variant& value)
// If it is this month. // If it is this month.
if (d < number && if (d < number &&
number <= Date::daysInMonth (m, y)) number <= ISO8601d::daysInMonth (m, y))
{ {
t->tm_hour = t->tm_min = t->tm_sec = 0; t->tm_hour = t->tm_min = t->tm_sec = 0;
t->tm_mon = m - 1; t->tm_mon = m - 1;

File diff suppressed because it is too large Load diff

View file

@ -23,6 +23,7 @@
// http://www.opensource.org/licenses/mit-license.php // http://www.opensource.org/licenses/mit-license.php
// //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_ISO8601 #ifndef INCLUDED_ISO8601
#define INCLUDED_ISO8601 #define INCLUDED_ISO8601
@ -33,15 +34,84 @@
class ISO8601d class ISO8601d
{ {
public: public:
static std::string weekstart;
static int minimumMatchLength;
static bool isoEnabled;
ISO8601d (); ISO8601d ();
ISO8601d (const std::string&, const std::string& format = "");
ISO8601d (time_t);
ISO8601d (const int, const int, const int);
ISO8601d (const int, const int, const int, const int, const int, const int);
~ISO8601d (); ~ISO8601d ();
ISO8601d (const ISO8601d&); // Unimplemented
ISO8601d& operator= (const ISO8601d&); // Unimplemented
operator time_t () const; operator time_t () const;
bool parse (const std::string&, std::string::size_type&); bool parse (const std::string&, std::string::size_type&, const std::string& format = "");
void clear ();
time_t toEpoch ();
std::string toEpochString ();
std::string toISO ();
double toJulian ();
void toMDY (int&, int&, int&);
const std::string toString (const std::string& format = "m/d/Y") const;
ISO8601d startOfDay () const;
ISO8601d startOfWeek () const;
ISO8601d startOfMonth () const;
ISO8601d startOfYear () const;
static bool valid (const std::string&, const std::string& format = "");
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 valid (const int, const int);
static bool leapYear (int);
static int daysInMonth (int, int);
static int daysInYear (int);
static std::string monthName (int);
static void dayName (int, std::string&);
static std::string dayName (int);
static int dayOfWeek (const std::string&);
static int dayOfWeek (int, int, int);
static int monthOfYear (const std::string&);
static int length (const std::string&);
int month () const;
int week () const;
int day () const;
int year () const;
int weekOfYear (int) const;
int dayOfWeek () const;
int dayOfYear () const;
int hour () const;
int minute () const;
int second () const;
bool operator== (const ISO8601d&) const;
bool operator!= (const ISO8601d&) const;
bool operator< (const ISO8601d&) const;
bool operator> (const ISO8601d&) const;
bool operator<= (const ISO8601d&) const;
bool operator>= (const ISO8601d&) const;
bool sameHour (const ISO8601d&) const;
bool sameDay (const ISO8601d&) const;
bool sameWeek (const ISO8601d&) const;
bool sameMonth (const ISO8601d&) const;
bool sameYear (const ISO8601d&) const;
ISO8601d operator+ (time_t);
ISO8601d operator+ (const int);
ISO8601d operator- (const int);
ISO8601d& operator+= (const int);
ISO8601d& operator-= (const int);
time_t operator- (const ISO8601d&);
void operator-- (); // Prefix
void operator-- (int); // Postfix
void operator++ (); // Prefix
void operator++ (int); // Postfix
private: private:
void clear ();
bool parse_formatted (Nibbler&, const std::string&);
bool parse_named (Nibbler&);
bool parse_epoch (Nibbler&);
bool parse_date_time (Nibbler&); bool parse_date_time (Nibbler&);
bool parse_date_time_ext (Nibbler&); bool parse_date_time_ext (Nibbler&);
bool parse_date_ext (Nibbler&); bool parse_date_ext (Nibbler&);
@ -49,7 +119,6 @@ private:
bool parse_time_ext (Nibbler&); bool parse_time_ext (Nibbler&);
bool parse_time_utc_ext (Nibbler&); bool parse_time_utc_ext (Nibbler&);
bool parse_time_off_ext (Nibbler&); bool parse_time_off_ext (Nibbler&);
int dayOfWeek (int, int, int);
bool validate (); bool validate ();
void resolve (); void resolve ();
@ -63,13 +132,15 @@ public:
int _seconds; int _seconds;
int _offset; int _offset;
bool _utc; bool _utc;
time_t _value; time_t _date;
}; };
// Period // Period
class ISO8601p class ISO8601p
{ {
public: public:
static bool isoEnabled;
ISO8601p (); ISO8601p ();
ISO8601p (time_t); ISO8601p (time_t);
ISO8601p (const std::string&); ISO8601p (const std::string&);
@ -81,11 +152,11 @@ public:
operator std::string () const; operator std::string () const;
operator time_t () const; operator time_t () const;
bool parse (const std::string&, std::string::size_type&); bool parse (const std::string&, std::string::size_type&);
void clear ();
const std::string format () const; const std::string format () const;
const std::string formatVague () const; const std::string formatVague () const;
private: private:
void clear ();
bool parse_designated (Nibbler&); bool parse_designated (Nibbler&);
bool validate (); bool validate ();
void resolve (); void resolve ();
@ -97,11 +168,9 @@ public:
int _hours; int _hours;
int _minutes; int _minutes;
int _seconds; int _seconds;
time_t _value; time_t _period;
}; };
// TODO Recurrence
#endif #endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View file

@ -28,14 +28,12 @@
#include <ctype.h> #include <ctype.h>
#include <Lexer.h> #include <Lexer.h>
#include <ISO8601.h> #include <ISO8601.h>
#include <Date.h>
#include <utf8.h> #include <utf8.h>
static const std::string uuid_pattern = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; static const std::string uuid_pattern = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
static const unsigned int uuid_min_length = 8; static const unsigned int uuid_min_length = 8;
std::string Lexer::dateFormat = ""; std::string Lexer::dateFormat = "";
bool Lexer::isoEnabled = true;
std::string::size_type Lexer::minimumMatchLength = 3; std::string::size_type Lexer::minimumMatchLength = 3;
std::map <std::string, std::string> Lexer::attributes; std::map <std::string, std::string> Lexer::attributes;
@ -432,39 +430,19 @@ bool Lexer::isString (std::string& token, Lexer::Type& type, const std::string&
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Lexer::Type::date // Lexer::Type::date
// <ISO8601d> | <Date> // <ISO8601d>
bool Lexer::isDate (std::string& token, Lexer::Type& type) bool Lexer::isDate (std::string& token, Lexer::Type& type)
{ {
// Try an ISO date parse. // Try an ISO date parse.
if (Lexer::isoEnabled)
{
std::size_t iso_i = 0; std::size_t iso_i = 0;
ISO8601d iso; ISO8601d iso;
if (iso.parse (_text.substr (_cursor), iso_i)) if (iso.parse (_text.substr (_cursor), iso_i, Lexer::dateFormat))
{ {
type = Lexer::Type::date; type = Lexer::Type::date;
token = _text.substr (_cursor, iso_i); token = _text.substr (_cursor, iso_i);
_cursor += iso_i; _cursor += iso_i;
return true; return true;
} }
}
// Try a legacy rc.dateformat parse here.
if (Lexer::dateFormat != "")
{
try
{
std::size_t legacy_i = 0;
Date legacyDate (_text.substr (_cursor), legacy_i, Lexer::dateFormat, false, false);
type = Lexer::Type::date;
token = _text.substr (_cursor, legacy_i);
_cursor += legacy_i;
return true;
}
catch (...) { /* Never mind. */ }
}
return false; return false;
} }

View file

@ -40,7 +40,6 @@ class Lexer
public: public:
// These are overridable. // These are overridable.
static std::string dateFormat; static std::string dateFormat;
static bool isoEnabled;
static std::string::size_type minimumMatchLength; static std::string::size_type minimumMatchLength;
static std::map <std::string, std::string> attributes; static std::map <std::string, std::string> attributes;

View file

@ -33,7 +33,7 @@
#include <Nibbler.h> #include <Nibbler.h>
#include <util.h> #include <util.h>
#ifdef NIBBLER_FEATURE_DATE #ifdef NIBBLER_FEATURE_DATE
#include <Date.h> #include <ISO8601.h>
#endif #endif
#ifdef NIBBLER_FEATURE_REGEX #ifdef NIBBLER_FEATURE_REGEX
#include <RX.h> #include <RX.h>
@ -708,7 +708,8 @@ bool Nibbler::getDateISO (time_t& t)
// Parse the longest integer using the next 'limit' characters of 'result' // Parse the longest integer using the next 'limit' characters of 'result'
// following position 'i' (when strict is true, the number of digits must be // following position 'i' (when strict is true, the number of digits must be
// equal to limit). // equal to limit).
bool Nibbler::parseDigits(std::string::size_type& i, bool Nibbler::parseDigits(
std::string::size_type& i,
int& result, int& result,
unsigned int limit, unsigned int limit,
bool strict /* = true */) bool strict /* = true */)
@ -819,8 +820,8 @@ bool Nibbler::getDate (const std::string& format, time_t& t)
! Lexer::isDigit ((*_input)[i + 1]) && ! Lexer::isDigit ((*_input)[i + 1]) &&
! Lexer::isDigit ((*_input)[i + 2])) ! Lexer::isDigit ((*_input)[i + 2]))
{ {
wday = Date::dayOfWeek (_input->substr (i, 3).c_str ()); wday = ISO8601d::dayOfWeek (_input->substr (i, 3).c_str ());
i += (format[f] == 'a') ? 3 : Date::dayName (wday).size (); i += (format[f] == 'a') ? 3 : ISO8601d::dayName (wday).size ();
} }
else else
return false; return false;
@ -835,8 +836,8 @@ bool Nibbler::getDate (const std::string& format, time_t& t)
{ {
if (month != -1) if (month != -1)
return false; return false;
month = Date::monthOfYear (_input->substr (i, 3).c_str()); month = ISO8601d::monthOfYear (_input->substr (i, 3).c_str());
i += (format[f] == 'b') ? 3 : Date::monthName (month).size (); i += (format[f] == 'b') ? 3 : ISO8601d::monthName (month).size ();
} }
else else
return false; return false;
@ -858,7 +859,7 @@ bool Nibbler::getDate (const std::string& format, time_t& t)
// now. // now.
if (year == -1) if (year == -1)
{ {
Date now = Date (); ISO8601d now;
year = now.year (); year = now.year ();
if (month == -1) if (month == -1)
{ {
@ -889,7 +890,7 @@ bool Nibbler::getDate (const std::string& format, time_t& t)
second = (second == -1) ? 0 : second; second = (second == -1) ? 0 : second;
// Check that values are correct // Check that values are correct
if (! Date::valid (month, day, year, hour, minute, second)) if (! ISO8601d::valid (month, day, year, hour, minute, second))
return false; return false;
// Convert to epoch. // Convert to epoch.

View file

@ -57,10 +57,6 @@ public:
bool getUntilEOL (std::string&); bool getUntilEOL (std::string&);
bool getUntilEOS (std::string&); bool getUntilEOS (std::string&);
/*
bool getAllOneOf (const std::string&, std::string&);
*/
bool getN (const int, std::string&); bool getN (const int, std::string&);
bool getQuoted (char, std::string&, bool quote = false); bool getQuoted (char, std::string&, bool quote = false);
bool getDigit (int&); bool getDigit (int&);

View file

@ -34,7 +34,7 @@
#include <signal.h> #include <signal.h>
#include <Context.h> #include <Context.h>
#include <Color.h> #include <Color.h>
#include <Date.h> #include <ISO8601.h>
#include <i18n.h> #include <i18n.h>
#include <text.h> #include <text.h>
#include <util.h> #include <util.h>
@ -638,7 +638,7 @@ void TDB2::update (
// old <task> // old <task>
// new <task> // new <task>
// --- // ---
undo.add_line ("time " + Date ().toEpochString () + "\n"); undo.add_line ("time " + ISO8601d ().toEpochString () + "\n");
undo.add_line ("old " + original.composeF4 () + "\n"); undo.add_line ("old " + original.composeF4 () + "\n");
undo.add_line ("new " + task.composeF4 () + "\n"); undo.add_line ("new " + task.composeF4 () + "\n");
undo.add_line ("---\n"); undo.add_line ("---\n");
@ -657,7 +657,7 @@ void TDB2::update (
// time <time> // time <time>
// new <task> // new <task>
// --- // ---
undo.add_line ("time " + Date ().toEpochString () + "\n"); undo.add_line ("time " + ISO8601d ().toEpochString () + "\n");
undo.add_line ("new " + task.composeF4 () + "\n"); undo.add_line ("new " + task.composeF4 () + "\n");
undo.add_line ("---\n"); undo.add_line ("---\n");
} }
@ -962,7 +962,7 @@ void TDB2::show_diff (
const std::string& prior, const std::string& prior,
const std::string& when) const std::string& when)
{ {
Date lastChange (strtol (when.c_str (), NULL, 10)); ISO8601d lastChange (strtol (when.c_str (), NULL, 10));
// Set the colors. // Set the colors.
Color color_red (context.color () ? context.config.get ("color.undo.before") : ""); Color color_red (context.color () ? context.config.get ("color.undo.before") : "");
@ -1209,7 +1209,7 @@ int TDB2::gc ()
// Scan all pending tasks, looking for any that need to be relocated to // Scan all pending tasks, looking for any that need to be relocated to
// completed, or need to be 'woken'. // completed, or need to be 'woken'.
Date now; ISO8601d now;
std::string status; std::string status;
for (auto& task : pending_tasks) for (auto& task : pending_tasks)
{ {
@ -1221,7 +1221,7 @@ int TDB2::gc ()
} }
else if (status == "waiting") else if (status == "waiting")
{ {
Date wait (task.get_date ("wait")); ISO8601d wait (task.get_date ("wait"));
if (wait < now) if (wait < now)
{ {
task.set ("status", "pending"); task.set ("status", "pending");
@ -1261,7 +1261,7 @@ int TDB2::gc ()
} }
else if (status == "waiting") else if (status == "waiting")
{ {
Date wait (task.get_date ("wait")); ISO8601d wait (task.get_date ("wait"));
if (wait < now) if (wait < now)
{ {
task.set ("status", "pending"); task.set ("status", "pending");

View file

@ -40,7 +40,6 @@
#include <Lexer.h> #include <Lexer.h>
#include <Nibbler.h> #include <Nibbler.h>
#endif #endif
#include <Date.h>
#include <ISO8601.h> #include <ISO8601.h>
#include <Task.h> #include <Task.h>
#ifdef PRODUCT_TASKWARRIOR #ifdef PRODUCT_TASKWARRIOR
@ -341,9 +340,9 @@ Task::dateState Task::getDateState (const std::string& name) const
std::string value = get (name); std::string value = get (name);
if (value.length ()) if (value.length ())
{ {
Date reference (value); ISO8601d reference (value);
Date now; ISO8601d now;
Date today ("today"); ISO8601d today ("today");
if (reference < today) if (reference < today)
return dateBeforeToday; return dateBeforeToday;
@ -360,7 +359,7 @@ Task::dateState Task::getDateState (const std::string& name) const
if (imminentperiod == 0) if (imminentperiod == 0)
return dateAfterToday; return dateAfterToday;
Date imminentDay = today + imminentperiod * 86400; ISO8601d imminentDay = today + imminentperiod * 86400;
if (reference < imminentDay) if (reference < imminentDay)
return dateAfterToday; return dateAfterToday;
} }
@ -377,7 +376,7 @@ bool Task::is_ready () const
return getStatus () == Task::pending && return getStatus () == Task::pending &&
! is_blocked && ! is_blocked &&
(! has ("scheduled") || (! has ("scheduled") ||
Date ("now").operator> (get_date ("scheduled"))); ISO8601d ("now").operator> (get_date ("scheduled")));
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -411,7 +410,7 @@ bool Task::is_dueyesterday () const
if (status != Task::completed && if (status != Task::completed &&
status != Task::deleted) status != Task::deleted)
{ {
if (Date ("yesterday").sameDay (get_date ("due"))) if (ISO8601d ("yesterday").sameDay (get_date ("due")))
return true; return true;
} }
} }
@ -449,7 +448,7 @@ bool Task::is_duetomorrow () const
if (status != Task::completed && if (status != Task::completed &&
status != Task::deleted) status != Task::deleted)
{ {
if (Date ("tomorrow").sameDay (get_date ("due"))) if (ISO8601d ("tomorrow").sameDay (get_date ("due")))
return true; return true;
} }
} }
@ -467,9 +466,9 @@ bool Task::is_dueweek () const
if (status != Task::completed && if (status != Task::completed &&
status != Task::deleted) status != Task::deleted)
{ {
Date due (get_date ("due")); ISO8601d due (get_date ("due"));
if (due >= Date ("socw") && if (due >= ISO8601d ("socw") &&
due <= Date ("eocw")) due <= ISO8601d ("eocw"))
return true; return true;
} }
} }
@ -487,9 +486,9 @@ bool Task::is_duemonth () const
if (status != Task::completed && if (status != Task::completed &&
status != Task::deleted) status != Task::deleted)
{ {
Date due (get_date ("due")); ISO8601d due (get_date ("due"));
if (due >= Date ("socm") && if (due >= ISO8601d ("socm") &&
due <= Date ("eocm")) due <= ISO8601d ("eocm"))
return true; return true;
} }
} }
@ -507,8 +506,8 @@ bool Task::is_dueyear () const
if (status != Task::completed && if (status != Task::completed &&
status != Task::deleted) status != Task::deleted)
{ {
Date now; ISO8601d now;
Date due (get_date ("due")); ISO8601d due (get_date ("due"));
if (now.year () == due.year ()) if (now.year () == due.year ())
return true; return true;
} }
@ -674,7 +673,7 @@ void Task::parseJSON (const json::object* root_obj)
// TW-1274 Standardization. // TW-1274 Standardization.
else if (i.first == "modification") else if (i.first == "modification")
{ {
Date d (unquoteText (i.second->dump ())); ISO8601d d (unquoteText (i.second->dump ()));
set ("modified", d.toEpochString ()); set ("modified", d.toEpochString ());
} }
@ -682,7 +681,7 @@ void Task::parseJSON (const json::object* root_obj)
else if (type == "date") else if (type == "date")
{ {
std::string text = unquoteText (i.second->dump ()); std::string text = unquoteText (i.second->dump ());
Date d (text); ISO8601d d (text);
set (i.first, text == "" ? "" : d.toEpochString ()); set (i.first, text == "" ? "" : d.toEpochString ());
} }
@ -747,7 +746,7 @@ void Task::parseJSON (const json::object* root_obj)
if (! what) if (! what)
throw format (STRING_TASK_NO_DESC, root_obj->dump ()); throw format (STRING_TASK_NO_DESC, root_obj->dump ());
std::string name = "annotation_" + Date (when->_data).toEpochString (); std::string name = "annotation_" + ISO8601d (when->_data).toEpochString ();
annos.insert (std::make_pair (name, json::decode (what->_data))); annos.insert (std::make_pair (name, json::decode (what->_data)));
} }
@ -865,7 +864,7 @@ std::string Task::composeJSON (bool decorate /*= false*/) const
// Date fields are written as ISO 8601. // Date fields are written as ISO 8601.
if (type == "date") if (type == "date")
{ {
Date d (i.second); ISO8601d d (i.second);
out << "\"" out << "\""
<< (i.first == "modification" ? "modified" : i.first) << (i.first == "modification" ? "modified" : i.first)
<< "\":\"" << "\":\""
@ -960,7 +959,7 @@ std::string Task::composeJSON (bool decorate /*= false*/) const
if (annotations_written) if (annotations_written)
out << ","; out << ",";
Date d (i.first.substr (11)); ISO8601d d (i.first.substr (11));
out << "{\"entry\":\"" out << "{\"entry\":\""
<< d.toISO () << d.toISO ()
<< "\",\"description\":\"" << "\",\"description\":\""
@ -1487,9 +1486,9 @@ void Task::validate (bool applyDefault /* = true */)
{ {
ISO8601p dur (Task::defaultDue); ISO8601p dur (Task::defaultDue);
if ((time_t) dur != 0) if ((time_t) dur != 0)
set ("due", (Date () + dur).toEpoch ()); set ("due", (ISO8601d () + dur).toEpoch ());
else else
set ("due", Date (Task::defaultDue).toEpoch ()); set ("due", ISO8601d (Task::defaultDue).toEpoch ());
} }
} }
@ -1568,11 +1567,11 @@ void Task::validate_before (const std::string& left, const std::string& right)
if (has (left) && if (has (left) &&
has (right)) has (right))
{ {
Date date_left (get_date (left)); ISO8601d date_left (get_date (left));
Date date_right (get_date (right)); ISO8601d date_right (get_date (right));
// if date is zero, then it is being removed (e.g. "due: wait:1day") // if date is zero, then it is being removed (e.g. "due: wait:1day")
if (date_left > date_right && date_right != 0) if (date_left > date_right && date_right.toEpoch () != 0)
context.footnote (format (STRING_TASK_VALID_BEFORE, left, right)); context.footnote (format (STRING_TASK_VALID_BEFORE, left, right));
} }
#endif #endif
@ -1923,8 +1922,8 @@ float Task::urgency_due () const
{ {
if (has ("due")) if (has ("due"))
{ {
Date now; ISO8601d now;
Date due (get_date ("due")); ISO8601d due (get_date ("due"));
// Map a range of 21 days to the value 0.2 - 1.0 // Map a range of 21 days to the value 0.2 - 1.0
float days_overdue = (now - due) / 86400.0; float days_overdue = (now - due) / 86400.0;
@ -1941,8 +1940,8 @@ float Task::urgency_age () const
{ {
assert (has ("entry")); assert (has ("entry"));
Date now; ISO8601d now;
Date entry (get_date ("entry")); ISO8601d entry (get_date ("entry"));
int age = (now - entry) / 86400; // in days int age = (now - entry) / 86400; // in days
if (Task::urgencyAgeMax == 0 || age > Task::urgencyAgeMax) if (Task::urgencyAgeMax == 0 || age > Task::urgencyAgeMax)

View file

@ -33,7 +33,6 @@
#include <Variant.h> #include <Variant.h>
#include <ISO8601.h> #include <ISO8601.h>
#include <Lexer.h> #include <Lexer.h>
#include <Date.h>
#include <RX.h> #include <RX.h>
#include <text.h> #include <text.h>
#include <i18n.h> #include <i18n.h>
@ -41,7 +40,6 @@
std::string Variant::dateFormat = ""; std::string Variant::dateFormat = "";
bool Variant::searchCaseSensitive = true; bool Variant::searchCaseSensitive = true;
bool Variant::searchUsingRegex = true; bool Variant::searchUsingRegex = true;
bool Variant::isoEnabled = true;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
Variant::Variant () Variant::Variant ()
@ -1010,8 +1008,8 @@ bool Variant::operator_partial (const Variant& other) const
case type_date: case type_date:
{ {
left.cast (type_date); left.cast (type_date);
Date left_date (left._date); ISO8601d left_date (left._date);
Date right_date (right._date); ISO8601d right_date (right._date);
return left_date.sameDay (right_date); return left_date.sameDay (right_date);
} }
@ -1031,8 +1029,8 @@ bool Variant::operator_partial (const Variant& other) const
case type_date: case type_date:
{ {
left.cast (type_date); left.cast (type_date);
Date left_date (left._date); ISO8601d left_date (left._date);
Date right_date (right._date); ISO8601d right_date (right._date);
return left_date.sameDay (right_date); return left_date.sameDay (right_date);
} }
@ -1057,8 +1055,8 @@ bool Variant::operator_partial (const Variant& other) const
case type_date: case type_date:
{ {
left.cast (type_date); left.cast (type_date);
Date left_date (left._date); ISO8601d left_date (left._date);
Date right_date (right._date); ISO8601d right_date (right._date);
return left_date.sameDay (right_date); return left_date.sameDay (right_date);
} }
@ -1100,8 +1098,8 @@ bool Variant::operator_partial (const Variant& other) const
case type_date: case type_date:
{ {
left.cast (type_date); left.cast (type_date);
Date left_date (left._date); ISO8601d left_date (left._date);
Date right_date (right._date); ISO8601d right_date (right._date);
return left_date.sameDay (right_date); return left_date.sameDay (right_date);
} }
@ -1123,8 +1121,8 @@ bool Variant::operator_partial (const Variant& other) const
case type_duration: case type_duration:
{ {
right.cast (type_date); right.cast (type_date);
Date left_date (left._date); ISO8601d left_date (left._date);
Date right_date (right._date); ISO8601d right_date (right._date);
return left_date.sameDay (right_date); return left_date.sameDay (right_date);
} }
} }
@ -1933,30 +1931,27 @@ void Variant::cast (const enum type new_type)
case type_date: case type_date:
{ {
_date = 0; _date = 0;
ISO8601d iso; ISO8601d iso;
std::string::size_type pos = 0; std::string::size_type pos = 0;
if (isoEnabled && if (iso.parse (_string, pos, dateFormat) &&
iso.parse (_string, pos) &&
pos == _string.length ()) pos == _string.length ())
{ {
_date = (time_t) iso; _date = iso.toEpoch ();
break; break;
} }
pos = 0; pos = 0;
ISO8601p isop; ISO8601p isop;
if (isoEnabled && if (isop.parse (_string, pos) &&
isop.parse (_string, pos) &&
pos == _string.length ()) pos == _string.length ())
{ {
_date = Date ().toEpoch () + (time_t) isop; _date = ISO8601d ().toEpoch () + (time_t) isop;
break; break;
} }
if (dateFormat != "") if (dateFormat != "")
{ {
_date = Date (_string, dateFormat).toEpoch (); _date = ISO8601d (_string, dateFormat).toEpoch ();
break; break;
} }
} }

View file

@ -28,7 +28,6 @@
#include <math.h> #include <math.h>
#include <Context.h> #include <Context.h>
#include <ColDate.h> #include <ColDate.h>
#include <Date.h>
#include <ISO8601.h> #include <ISO8601.h>
#include <text.h> #include <text.h>
#include <i18n.h> #include <i18n.h>
@ -50,15 +49,15 @@ ColumnDate::ColumnDate ()
"remaining", "remaining",
"countdown"}; "countdown"};
Date now; ISO8601d now;
now -= 125; // So that "age" is non-zero. now -= 125; // So that "age" is non-zero.
_examples = {now.toString (context.config.get ("dateformat")), _examples = {now.toString (context.config.get ("dateformat")),
format (now.toJulian (), 13, 12), format (now.toJulian (), 13, 12),
now.toEpochString (), now.toEpochString (),
now.toISO (), now.toISO (),
ISO8601p (Date () - now).formatVague (), ISO8601p (ISO8601d () - now).formatVague (),
"", "",
ISO8601p (Date () - now).format ()}; ISO8601p (ISO8601d () - now).format ()};
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -74,7 +73,7 @@ void ColumnDate::measure (Task& task, unsigned int& minimum, unsigned int& maxim
if (task.has (_name)) if (task.has (_name))
{ {
Date date (task.get_date (_name)); ISO8601d date (task.get_date (_name));
if (_style == "default" || if (_style == "default" ||
_style == "formatted") _style == "formatted")
@ -89,11 +88,11 @@ void ColumnDate::measure (Task& task, unsigned int& minimum, unsigned int& maxim
if (format == "") if (format == "")
format = context.config.get ("dateformat"); format = context.config.get ("dateformat");
minimum = maximum = Date::length (format); minimum = maximum = ISO8601d::length (format);
} }
else if (_style == "countdown") else if (_style == "countdown")
{ {
Date now; ISO8601d now;
minimum = maximum = ISO8601p (now - date).formatVague ().length (); minimum = maximum = ISO8601p (now - date).formatVague ().length ();
} }
else if (_style == "julian") else if (_style == "julian")
@ -110,12 +109,12 @@ void ColumnDate::measure (Task& task, unsigned int& minimum, unsigned int& maxim
} }
else if (_style == "age") else if (_style == "age")
{ {
Date now; ISO8601d now;
minimum = maximum = ISO8601p (now - date).formatVague ().length (); minimum = maximum = ISO8601p (now - date).formatVague ().length ();
} }
else if (_style == "remaining") else if (_style == "remaining")
{ {
Date now; ISO8601d now;
if (date > now) if (date > now)
minimum = maximum = ISO8601p (date - now).formatVague ().length (); minimum = maximum = ISO8601p (date - now).formatVague ().length ();
} }
@ -133,7 +132,7 @@ void ColumnDate::render (
{ {
if (task.has (_name)) if (task.has (_name))
{ {
Date date (task.get_date (_name)); ISO8601d date (task.get_date (_name));
if (_style == "default" || if (_style == "default" ||
_style == "formatted") _style == "formatted")
@ -155,7 +154,7 @@ void ColumnDate::render (
} }
else if (_style == "countdown") else if (_style == "countdown")
{ {
Date now; ISO8601d now;
lines.push_back ( lines.push_back (
color.colorize ( color.colorize (
@ -185,7 +184,7 @@ void ColumnDate::render (
} }
else if (_style == "age") else if (_style == "age")
{ {
Date now; ISO8601d now;
lines.push_back ( lines.push_back (
color.colorize ( color.colorize (
@ -194,7 +193,7 @@ void ColumnDate::render (
} }
else if (_style == "remaining") else if (_style == "remaining")
{ {
Date now; ISO8601d now;
if (date > now) if (date > now)
lines.push_back ( lines.push_back (
color.colorize ( color.colorize (

View file

@ -27,7 +27,7 @@
#include <cmake.h> #include <cmake.h>
#include <stdlib.h> #include <stdlib.h>
#include <Context.h> #include <Context.h>
#include <Date.h> #include <ISO8601.h>
#include <ColDescription.h> #include <ColDescription.h>
#include <text.h> #include <text.h>
#include <utf8.h> #include <utf8.h>
@ -55,7 +55,7 @@ ColumnDescription::ColumnDescription ()
if (_dateformat == "") if (_dateformat == "")
_dateformat = context.config.get ("dateformat"); _dateformat = context.config.get ("dateformat");
std::string t = Date ().toString (_dateformat); std::string t = ISO8601d ().toString (_dateformat);
std::string d = STRING_COLUMN_EXAMPLES_DESC; std::string d = STRING_COLUMN_EXAMPLES_DESC;
std::string a1 = STRING_COLUMN_EXAMPLES_ANNO1; std::string a1 = STRING_COLUMN_EXAMPLES_ANNO1;
std::string a2 = STRING_COLUMN_EXAMPLES_ANNO2; std::string a2 = STRING_COLUMN_EXAMPLES_ANNO2;
@ -102,7 +102,7 @@ void ColumnDescription::measure (Task& task, unsigned int& minimum, unsigned int
if (task.annotation_count) if (task.annotation_count)
{ {
unsigned int min_anno = _indent + Date::length (_dateformat); unsigned int min_anno = _indent + ISO8601d::length (_dateformat);
if (min_anno > minimum) if (min_anno > minimum)
minimum = min_anno; minimum = min_anno;
@ -132,7 +132,7 @@ void ColumnDescription::measure (Task& task, unsigned int& minimum, unsigned int
if (task.annotation_count) if (task.annotation_count)
{ {
auto min_anno = Date::length (_dateformat); auto min_anno = ISO8601d::length (_dateformat);
std::map <std::string, std::string> annos; std::map <std::string, std::string> annos;
task.getAnnotations (annos); task.getAnnotations (annos);
for (auto& i : annos) for (auto& i : annos)
@ -187,7 +187,7 @@ void ColumnDescription::render (
{ {
for (auto& i : annos) for (auto& i : annos)
{ {
Date dt (strtol (i.first.substr (11).c_str (), NULL, 10)); ISO8601d dt (strtol (i.first.substr (11).c_str (), NULL, 10));
description += "\n" + std::string (_indent, ' ') + dt.toString (_dateformat) + " " + i.second; description += "\n" + std::string (_indent, ' ') + dt.toString (_dateformat) + " " + i.second;
} }
} }
@ -218,7 +218,7 @@ void ColumnDescription::render (
{ {
for (auto& i : annos) for (auto& i : annos)
{ {
Date dt (atoi (i.first.substr (11).c_str ())); ISO8601d dt (strtol (i.first.substr (11).c_str (), NULL, 10));
description += " " + dt.toString (_dateformat) + " " + i.second; description += " " + dt.toString (_dateformat) + " " + i.second;
} }
} }

View file

@ -28,8 +28,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <Context.h> #include <Context.h>
#include <ColDue.h> #include <ColDue.h>
#include <Date.h>
#include <ISO8601.h>
#include <text.h> #include <text.h>
#include <i18n.h> #include <i18n.h>

View file

@ -28,8 +28,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <Context.h> #include <Context.h>
#include <ColScheduled.h> #include <ColScheduled.h>
#include <Date.h>
#include <ISO8601.h>
#include <text.h> #include <text.h>
#include <i18n.h> #include <i18n.h>

View file

@ -27,7 +27,6 @@
#include <cmake.h> #include <cmake.h>
#include <Context.h> #include <Context.h>
#include <ISO8601.h> #include <ISO8601.h>
#include <Date.h>
#include <ColUDA.h> #include <ColUDA.h>
#include <text.h> #include <text.h>
#include <utf8.h> #include <utf8.h>
@ -89,14 +88,14 @@ void ColumnUDA::measure (Task& task, unsigned int& minimum, unsigned int& maximu
// rc.report.<report>.dateformat // rc.report.<report>.dateformat
// rc.dateformat.report // rc.dateformat.report
// rc.dateformat // rc.dateformat
Date date ((time_t) strtol (value.c_str (), NULL, 10)); ISO8601d date ((time_t) strtol (value.c_str (), NULL, 10));
std::string format = context.config.get ("report." + _report + ".dateformat"); std::string format = context.config.get ("report." + _report + ".dateformat");
if (format == "") if (format == "")
format = context.config.get ("dateformat.report"); format = context.config.get ("dateformat.report");
if (format == "") if (format == "")
format = context.config.get ("dateformat"); format = context.config.get ("dateformat");
minimum = maximum = Date::length (format); minimum = maximum = ISO8601d::length (format);
} }
else if (_type == "duration") else if (_type == "duration")
{ {
@ -153,8 +152,7 @@ void ColumnUDA::render (
lines.push_back ( lines.push_back (
color.colorize ( color.colorize (
leftJustify ( leftJustify (
Date ((time_t) strtol (value.c_str (), NULL, 10)) ISO8601d ((time_t) strtol (value.c_str (), NULL, 10)).toString (format), width)));
.toString (format), width)));
} }
else if (_type == "duration") else if (_type == "duration")
{ {

View file

@ -32,7 +32,6 @@
#include <math.h> #include <math.h>
#include <Context.h> #include <Context.h>
#include <Filter.h> #include <Filter.h>
#include <Date.h>
#include <ISO8601.h> #include <ISO8601.h>
#include <main.h> #include <main.h>
#include <i18n.h> #include <i18n.h>
@ -152,10 +151,10 @@ public:
private: private:
void generateBars (); void generateBars ();
void optimizeGrid (); void optimizeGrid ();
Date quantize (const Date&); ISO8601d quantize (const ISO8601d&);
Date increment (const Date&); ISO8601d increment (const ISO8601d&);
Date decrement (const Date&); ISO8601d decrement (const ISO8601d&);
void maxima (); void maxima ();
void yLabels (std::vector <int>&); void yLabels (std::vector <int>&);
void calculateRates (std::vector <time_t>&); void calculateRates (std::vector <time_t>&);
@ -173,7 +172,7 @@ public:
int _estimated_bars; // Estimated bar count int _estimated_bars; // Estimated bar count
int _actual_bars; // Calculated bar count int _actual_bars; // Calculated bar count
std::map <time_t, Bar> _bars; // Epoch-indexed set of bars std::map <time_t, Bar> _bars; // Epoch-indexed set of bars
Date _earliest; // Date of earliest estimated bar ISO8601d _earliest; // Date of earliest estimated bar
int _carryover_done; // Number of 'done' tasks prior to chart range int _carryover_done; // Number of 'done' tasks prior to chart range
char _period; // D, W, M char _period; // D, W, M
std::string _title; // Additional description std::string _title; // Additional description
@ -226,13 +225,13 @@ void Chart::scan (std::vector <Task>& tasks)
generateBars (); generateBars ();
// Not quantized, so that "while (xxx < now)" is inclusive. // Not quantized, so that "while (xxx < now)" is inclusive.
Date now; ISO8601d now;
time_t epoch; time_t epoch;
for (auto& task : tasks) for (auto& task : tasks)
{ {
// The entry date is when the counting starts. // The entry date is when the counting starts.
Date from = quantize (Date (task.get_date ("entry"))); ISO8601d from = quantize (ISO8601d (task.get_date ("entry")));
epoch = from.toEpoch (); epoch = from.toEpoch ();
if (_bars.find (epoch) != _bars.end ()) if (_bars.find (epoch) != _bars.end ())
@ -246,7 +245,7 @@ void Chart::scan (std::vector <Task>& tasks)
{ {
if (task.has ("start")) if (task.has ("start"))
{ {
Date start = quantize (Date (task.get_date ("start"))); ISO8601d start = quantize (ISO8601d (task.get_date ("start")));
while (from < start) while (from < start)
{ {
epoch = from.toEpoch (); epoch = from.toEpoch ();
@ -280,7 +279,7 @@ void Chart::scan (std::vector <Task>& tasks)
else if (status == Task::completed) else if (status == Task::completed)
{ {
// Truncate history so it starts at 'earliest' for completed tasks. // Truncate history so it starts at 'earliest' for completed tasks.
Date end = quantize (Date (task.get_date ("end"))); ISO8601d end = quantize (ISO8601d (task.get_date ("end")));
epoch = end.toEpoch (); epoch = end.toEpoch ();
if (_bars.find (epoch) != _bars.end ()) if (_bars.find (epoch) != _bars.end ())
@ -296,7 +295,7 @@ void Chart::scan (std::vector <Task>& tasks)
if (task.has ("start")) if (task.has ("start"))
{ {
Date start = quantize (Date (task.get_date ("start"))); ISO8601d start = quantize (ISO8601d (task.get_date ("start")));
while (from < start) while (from < start)
{ {
epoch = from.toEpoch (); epoch = from.toEpoch ();
@ -323,7 +322,7 @@ void Chart::scan (std::vector <Task>& tasks)
} }
else else
{ {
Date end = quantize (Date (task.get_date ("end"))); ISO8601d end = quantize (ISO8601d (task.get_date ("end")));
while (from < end) while (from < end)
{ {
epoch = from.toEpoch (); epoch = from.toEpoch ();
@ -347,7 +346,7 @@ void Chart::scan (std::vector <Task>& tasks)
else if (status == Task::deleted) else if (status == Task::deleted)
{ {
// Skip old deleted tasks. // Skip old deleted tasks.
Date end = quantize (Date (task.get_date ("end"))); ISO8601d end = quantize (ISO8601d (task.get_date ("end")));
epoch = end.toEpoch (); epoch = end.toEpoch ();
if (_bars.find (epoch) != _bars.end ()) if (_bars.find (epoch) != _bars.end ())
++_bars[epoch]._removed; ++_bars[epoch]._removed;
@ -357,7 +356,7 @@ void Chart::scan (std::vector <Task>& tasks)
if (task.has ("start")) if (task.has ("start"))
{ {
Date start = quantize (Date (task.get_date ("start"))); ISO8601d start = quantize (ISO8601d (task.get_date ("start")));
while (from < start) while (from < start)
{ {
epoch = from.toEpoch (); epoch = from.toEpoch ();
@ -376,7 +375,7 @@ void Chart::scan (std::vector <Task>& tasks)
} }
else else
{ {
Date end = quantize (Date (task.get_date ("end"))); ISO8601d end = quantize (ISO8601d (task.get_date ("end")));
while (from < end) while (from < end)
{ {
epoch = from.toEpoch (); epoch = from.toEpoch ();
@ -608,7 +607,7 @@ void Chart::optimizeGrid ()
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
Date Chart::quantize (const Date& input) ISO8601d Chart::quantize (const ISO8601d& input)
{ {
if (_period == 'D') return input.startOfDay (); if (_period == 'D') return input.startOfDay ();
if (_period == 'W') return input.startOfWeek (); if (_period == 'W') return input.startOfWeek ();
@ -618,7 +617,7 @@ Date Chart::quantize (const Date& input)
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
Date Chart::increment (const Date& input) ISO8601d Chart::increment (const ISO8601d& input)
{ {
// Move to the next period. // Move to the next period.
int d = input.day (); int d = input.day ();
@ -630,7 +629,7 @@ Date Chart::increment (const Date& input)
switch (_period) switch (_period)
{ {
case 'D': case 'D':
if (++d > Date::daysInMonth (m, y)) if (++d > ISO8601d::daysInMonth (m, y))
{ {
d = 1; d = 1;
@ -644,7 +643,7 @@ Date Chart::increment (const Date& input)
case 'W': case 'W':
d += 7; d += 7;
days = Date::daysInMonth (m, y); days = ISO8601d::daysInMonth (m, y);
if (d > days) if (d > days)
{ {
d -= days; d -= days;
@ -667,11 +666,11 @@ Date Chart::increment (const Date& input)
break; break;
} }
return Date (m, d, y, 0, 0, 0); return ISO8601d (m, d, y, 0, 0, 0);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
Date Chart::decrement (const Date& input) ISO8601d Chart::decrement (const ISO8601d& input)
{ {
// Move to the previous period. // Move to the previous period.
int d = input.day (); int d = input.day ();
@ -689,7 +688,7 @@ Date Chart::decrement (const Date& input)
--y; --y;
} }
d = Date::daysInMonth (m, y); d = ISO8601d::daysInMonth (m, y);
} }
break; break;
@ -703,7 +702,7 @@ Date Chart::decrement (const Date& input)
y--; y--;
} }
d += Date::daysInMonth (m, y); d += ISO8601d::daysInMonth (m, y);
} }
break; break;
@ -717,7 +716,7 @@ Date Chart::decrement (const Date& input)
break; break;
} }
return Date (m, d, y, 0, 0, 0); return ISO8601d (m, d, y, 0, 0, 0);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -727,12 +726,12 @@ void Chart::generateBars ()
Bar bar; Bar bar;
// Determine the last bar date. // Determine the last bar date.
Date cursor; ISO8601d cursor;
switch (_period) switch (_period)
{ {
case 'D': cursor = Date ().startOfDay (); break; case 'D': cursor = ISO8601d ().startOfDay (); break;
case 'W': cursor = Date ().startOfWeek (); break; case 'W': cursor = ISO8601d ().startOfWeek (); break;
case 'M': cursor = Date ().startOfMonth (); break; case 'M': cursor = ISO8601d ().startOfMonth (); break;
} }
// Iterate and determine all the other bar dates. // Iterate and determine all the other bar dates.
@ -744,7 +743,7 @@ void Chart::generateBars ()
{ {
case 'D': // month/day case 'D': // month/day
{ {
std::string month = Date::monthName (cursor.month ()); std::string month = ISO8601d::monthName (cursor.month ());
bar._major_label = month.substr (0, 3); bar._major_label = month.substr (0, 3);
sprintf (str, "%02d", cursor.day ()); sprintf (str, "%02d", cursor.day ());
@ -934,7 +933,7 @@ void Chart::calculateRates (std::vector <time_t>& sequence)
int current_pending = _bars[sequence.back ()]._pending; int current_pending = _bars[sequence.back ()]._pending;
int remaining_days = (int) (current_pending / (_fix_rate - _find_rate)); int remaining_days = (int) (current_pending / (_fix_rate - _find_rate));
Date now; ISO8601d now;
ISO8601p delta (remaining_days * 86400); ISO8601p delta (remaining_days * 86400);
now += delta; now += delta;

View file

@ -74,7 +74,7 @@ int CmdCalendar::execute (std::string& output)
handleRecurrence (); handleRecurrence ();
auto tasks = context.tdb2.pending.get_tasks (); auto tasks = context.tdb2.pending.get_tasks ();
Date today; ISO8601d today;
bool getpendingdate = false; bool getpendingdate = false;
int monthsToDisplay = 1; int monthsToDisplay = 1;
int mFrom = today.month (); int mFrom = today.month ();
@ -98,7 +98,7 @@ int CmdCalendar::execute (std::string& output)
// Set up a vector of months, for autoComplete. // Set up a vector of months, for autoComplete.
std::vector <std::string> monthNames; std::vector <std::string> monthNames;
for (int i = 1; i <= 12; ++i) for (int i = 1; i <= 12; ++i)
monthNames.push_back (lowerCase (Date::monthName (i))); monthNames.push_back (lowerCase (ISO8601d::monthName (i)));
// For autoComplete results. // For autoComplete results.
std::vector <std::string> matches; std::vector <std::string> matches;
@ -139,7 +139,7 @@ int CmdCalendar::execute (std::string& output)
// "January" etc. // "January" etc.
else if (autoComplete (lowerCase (arg), monthNames, matches, context.config.getInteger ("abbreviation.minimum")) == 1) else if (autoComplete (lowerCase (arg), monthNames, matches, context.config.getInteger ("abbreviation.minimum")) == 1)
{ {
argMonth = Date::monthOfYear (matches[0]); argMonth = ISO8601d::monthOfYear (matches[0]);
if (argMonth == -1) if (argMonth == -1)
throw format (STRING_CMD_CAL_BAD_MONTH, arg); throw format (STRING_CMD_CAL_BAD_MONTH, arg);
} }
@ -176,7 +176,7 @@ int CmdCalendar::execute (std::string& output)
if (getpendingdate == true) if (getpendingdate == true)
{ {
// Find the oldest pending due date. // Find the oldest pending due date.
Date oldest (12, 31, 2037); ISO8601d oldest (12, 31, 2037);
for (auto& task : tasks) for (auto& task : tasks)
{ {
if (task.getStatus () == Task::pending) if (task.getStatus () == Task::pending)
@ -185,7 +185,7 @@ int CmdCalendar::execute (std::string& output)
!task.hasTag ("nocal")) !task.hasTag ("nocal"))
{ {
++countDueDates; ++countDueDates;
Date d (task.get ("due")); ISO8601d d (task.get ("due"));
if (d < oldest) oldest = d; if (d < oldest) oldest = d;
} }
} }
@ -234,7 +234,7 @@ int CmdCalendar::execute (std::string& output)
// Print month headers (cheating on the width settings, yes) // Print month headers (cheating on the width settings, yes)
for (int i = 0 ; i < monthsPerLine ; i++) for (int i = 0 ; i < monthsPerLine ; i++)
{ {
std::string month = Date::monthName (nextM); std::string month = ISO8601d::monthName (nextM);
// 12345678901234567890123456 = 26 chars wide // 12345678901234567890123456 = 26 chars wide
// ^^ = center // ^^ = center
@ -317,7 +317,7 @@ int CmdCalendar::execute (std::string& output)
details_mFrom = 12; details_mFrom = 12;
--details_yFrom; --details_yFrom;
} }
int details_dFrom = Date::daysInMonth (details_mFrom, details_yFrom); int details_dFrom = ISO8601d::daysInMonth (details_mFrom, details_yFrom);
++mTo; ++mTo;
if (mTo == 13) if (mTo == 13)
@ -326,10 +326,10 @@ int CmdCalendar::execute (std::string& output)
++yTo; ++yTo;
} }
Date date_after (details_mFrom, details_dFrom, details_yFrom); ISO8601d date_after (details_mFrom, details_dFrom, details_yFrom);
std::string after = date_after.toString (context.config.get ("dateformat")); std::string after = date_after.toString (context.config.get ("dateformat"));
Date date_before (mTo, 1, yTo); ISO8601d date_before (mTo, 1, yTo);
std::string before = date_before.toString (context.config.get ("dateformat")); std::string before = date_before.toString (context.config.get ("dateformat"));
// Table with due date information // Table with due date information
@ -379,7 +379,7 @@ int CmdCalendar::execute (std::string& output)
{ {
std::string holName = context.config.get ("holiday." + it.first.substr (8, it.first.size () - 13) + ".name"); std::string holName = context.config.get ("holiday." + it.first.substr (8, it.first.size () - 13) + ".name");
std::string holDate = context.config.get ("holiday." + it.first.substr (8, it.first.size () - 13) + ".date"); std::string holDate = context.config.get ("holiday." + it.first.substr (8, it.first.size () - 13) + ".date");
Date hDate (holDate.c_str (), context.config.get ("dateformat.holiday")); ISO8601d hDate (holDate.c_str (), context.config.get ("dateformat.holiday"));
if (date_after < hDate && hDate < date_before) if (date_after < hDate && hDate < date_before)
hm[hDate.toEpoch()].push_back(holName); hm[hDate.toEpoch()].push_back(holName);
@ -396,7 +396,7 @@ int CmdCalendar::execute (std::string& output)
for (auto& hm_it : hm) for (auto& hm_it : hm)
{ {
std::vector <std::string> v = hm_it.second; std::vector <std::string> v = hm_it.second;
Date hDate (hm_it.first); ISO8601d hDate (hm_it.first);
std::string d = hDate.toString (format); std::string d = hDate.toString (format);
for (size_t i = 0; i < v.size(); i++) for (size_t i = 0; i < v.size(); i++)
{ {
@ -420,12 +420,12 @@ int CmdCalendar::execute (std::string& output)
std::string CmdCalendar::renderMonths ( std::string CmdCalendar::renderMonths (
int firstMonth, int firstMonth,
int firstYear, int firstYear,
const Date& today, const ISO8601d& today,
std::vector <Task>& all, std::vector <Task>& all,
int monthsPerLine) int monthsPerLine)
{ {
// What day of the week does the user consider the first? // What day of the week does the user consider the first?
int weekStart = Date::dayOfWeek (context.config.get ("weekstart")); int weekStart = ISO8601d::dayOfWeek (context.config.get ("weekstart"));
if (weekStart != 0 && weekStart != 1) if (weekStart != 0 && weekStart != 1)
throw std::string (STRING_CMD_CAL_SUN_MON); throw std::string (STRING_CMD_CAL_SUN_MON);
@ -440,24 +440,24 @@ std::string CmdCalendar::renderMonths (
if (weekStart == 1) if (weekStart == 1)
{ {
view.add (Column::factory ("string.right", " ")); view.add (Column::factory ("string.right", " "));
view.add (Column::factory ("string.right", utf8_substr (Date::dayName (1), 0, 2))); view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (1), 0, 2)));
view.add (Column::factory ("string.right", utf8_substr (Date::dayName (2), 0, 2))); view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (2), 0, 2)));
view.add (Column::factory ("string.right", utf8_substr (Date::dayName (3), 0, 2))); view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (3), 0, 2)));
view.add (Column::factory ("string.right", utf8_substr (Date::dayName (4), 0, 2))); view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (4), 0, 2)));
view.add (Column::factory ("string.right", utf8_substr (Date::dayName (5), 0, 2))); view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (5), 0, 2)));
view.add (Column::factory ("string.right", utf8_substr (Date::dayName (6), 0, 2))); view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (6), 0, 2)));
view.add (Column::factory ("string.right", utf8_substr (Date::dayName (0), 0, 2))); view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (0), 0, 2)));
} }
else else
{ {
view.add (Column::factory ("string.right", " ")); view.add (Column::factory ("string.right", " "));
view.add (Column::factory ("string.right", utf8_substr (Date::dayName (0), 0, 2))); view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (0), 0, 2)));
view.add (Column::factory ("string.right", utf8_substr (Date::dayName (1), 0, 2))); view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (1), 0, 2)));
view.add (Column::factory ("string.right", utf8_substr (Date::dayName (2), 0, 2))); view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (2), 0, 2)));
view.add (Column::factory ("string.right", utf8_substr (Date::dayName (3), 0, 2))); view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (3), 0, 2)));
view.add (Column::factory ("string.right", utf8_substr (Date::dayName (4), 0, 2))); view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (4), 0, 2)));
view.add (Column::factory ("string.right", utf8_substr (Date::dayName (5), 0, 2))); view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (5), 0, 2)));
view.add (Column::factory ("string.right", utf8_substr (Date::dayName (6), 0, 2))); view.add (Column::factory ("string.right", utf8_substr (ISO8601d::dayName (6), 0, 2)));
} }
} }
@ -487,7 +487,7 @@ std::string CmdCalendar::renderMonths (
years.push_back (++thisYear); years.push_back (++thisYear);
} }
months.push_back (thisMonth); months.push_back (thisMonth);
daysInMonth.push_back (Date::daysInMonth (thisMonth++, thisYear)); daysInMonth.push_back (ISO8601d::daysInMonth (thisMonth++, thisYear));
} }
int row = 0; int row = 0;
@ -510,7 +510,7 @@ std::string CmdCalendar::renderMonths (
// Loop through days in month and add to table. // Loop through days in month and add to table.
for (int d = 1; d <= daysInMonth[mpl]; ++d) for (int d = 1; d <= daysInMonth[mpl]; ++d)
{ {
Date temp (months[mpl], d, years[mpl]); ISO8601d temp (months[mpl], d, years[mpl]);
int dow = temp.dayOfWeek (); int dow = temp.dayOfWeek ();
int woy = temp.weekOfYear (weekStart); int woy = temp.weekOfYear (weekStart);
@ -543,7 +543,7 @@ std::string CmdCalendar::renderMonths (
if (hol.first.substr (hol.first.size () - 4) == "date") if (hol.first.substr (hol.first.size () - 4) == "date")
{ {
std::string value = hol.second; std::string value = hol.second;
Date holDate (value.c_str (), context.config.get ("dateformat.holiday")); ISO8601d holDate (value.c_str (), context.config.get ("dateformat.holiday"));
if (holDate.day () == d && if (holDate.day () == d &&
holDate.month () == months[mpl] && holDate.month () == months[mpl] &&
holDate.year () == years[mpl]) holDate.year () == years[mpl])
@ -568,7 +568,7 @@ std::string CmdCalendar::renderMonths (
task.has ("due")) task.has ("due"))
{ {
std::string due = task.get ("due"); std::string due = task.get ("due");
Date duedmy (strtol (due.c_str(), NULL, 10)); ISO8601d duedmy (strtol (due.c_str(), NULL, 10));
if (duedmy.day () == d && if (duedmy.day () == d &&
duedmy.month () == months[mpl] && duedmy.month () == months[mpl] &&

View file

@ -29,7 +29,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <Date.h> #include <ISO8601.h>
#include <Task.h> #include <Task.h>
#include <Command.h> #include <Command.h>
@ -40,7 +40,7 @@ public:
int execute (std::string&); int execute (std::string&);
private: private:
std::string renderMonths (int, int, const Date&, std::vector <Task>&, int); std::string renderMonths (int, int, const ISO8601d&, std::vector <Task>&, int);
}; };
#endif #endif

View file

@ -166,7 +166,7 @@ std::string CmdEdit::formatDate (
std::string value = task.get (attribute); std::string value = task.get (attribute);
if (value.length ()) if (value.length ())
{ {
Date dt (value); ISO8601d dt (value);
value = dt.toString (dateformat); value = dt.toString (dateformat);
} }
@ -250,12 +250,12 @@ std::string CmdEdit::formatTask (Task task, const std::string& dateformat)
task.getAnnotations (annotations); task.getAnnotations (annotations);
for (auto& anno : annotations) for (auto& anno : annotations)
{ {
Date dt (strtol (anno.first.substr (11).c_str (), NULL, 10)); ISO8601d dt (strtol (anno.first.substr (11).c_str (), NULL, 10));
before << " Annotation: " << dt.toString (dateformat) before << " Annotation: " << dt.toString (dateformat)
<< " -- " << json::encode (anno.second) << "\n"; << " -- " << json::encode (anno.second) << "\n";
} }
Date now; ISO8601d now;
before << " Annotation: " << now.toString (dateformat) << " -- \n"; before << " Annotation: " << now.toString (dateformat) << " -- \n";
// Add dependencies here. // Add dependencies here.
@ -379,7 +379,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string
if (formatted != value) if (formatted != value)
{ {
context.footnote (STRING_EDIT_ENTRY_MOD); context.footnote (STRING_EDIT_ENTRY_MOD);
task.set ("entry", Date(value, dateformat).toEpochString ()); task.set ("entry", ISO8601d (value, dateformat).toEpochString ());
} }
} }
else else
@ -396,13 +396,13 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string
if (formatted != value) if (formatted != value)
{ {
context.footnote (STRING_EDIT_START_MOD); context.footnote (STRING_EDIT_START_MOD);
task.set ("start", Date(value, dateformat).toEpochString ()); task.set ("start", ISO8601d (value, dateformat).toEpochString ());
} }
} }
else else
{ {
context.footnote (STRING_EDIT_START_MOD); context.footnote (STRING_EDIT_START_MOD);
task.set ("start", Date(value, dateformat).toEpochString ()); task.set ("start", ISO8601d (value, dateformat).toEpochString ());
} }
} }
else else
@ -425,7 +425,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string
if (formatted != value) if (formatted != value)
{ {
context.footnote (STRING_EDIT_END_MOD); context.footnote (STRING_EDIT_END_MOD);
task.set ("end", Date(value, dateformat).toEpochString ()); task.set ("end", ISO8601d (value, dateformat).toEpochString ());
} }
} }
else if (task.getStatus () != Task::deleted) else if (task.getStatus () != Task::deleted)
@ -452,13 +452,13 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string
if (formatted != value) if (formatted != value)
{ {
context.footnote (STRING_EDIT_SCHED_MOD); context.footnote (STRING_EDIT_SCHED_MOD);
task.set ("scheduled", Date(value, dateformat).toEpochString ()); task.set ("scheduled", ISO8601d (value, dateformat).toEpochString ());
} }
} }
else else
{ {
context.footnote (STRING_EDIT_SCHED_MOD); context.footnote (STRING_EDIT_SCHED_MOD);
task.set ("scheduled", Date(value, dateformat).toEpochString ()); task.set ("scheduled", ISO8601d (value, dateformat).toEpochString ());
} }
} }
else else
@ -482,13 +482,13 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string
if (formatted != value) if (formatted != value)
{ {
context.footnote (STRING_EDIT_DUE_MOD); context.footnote (STRING_EDIT_DUE_MOD);
task.set ("due", Date(value, dateformat).toEpochString ()); task.set ("due", ISO8601d (value, dateformat).toEpochString ());
} }
} }
else else
{ {
context.footnote (STRING_EDIT_DUE_MOD); context.footnote (STRING_EDIT_DUE_MOD);
task.set ("due", Date(value, dateformat).toEpochString ()); task.set ("due", ISO8601d (value, dateformat).toEpochString ());
} }
} }
else else
@ -519,13 +519,13 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string
if (formatted != value) if (formatted != value)
{ {
context.footnote (STRING_EDIT_UNTIL_MOD); context.footnote (STRING_EDIT_UNTIL_MOD);
task.set ("until", Date(value, dateformat).toEpochString ()); task.set ("until", ISO8601d (value, dateformat).toEpochString ());
} }
} }
else else
{ {
context.footnote (STRING_EDIT_UNTIL_MOD); context.footnote (STRING_EDIT_UNTIL_MOD);
task.set ("until", Date(value, dateformat).toEpochString ()); task.set ("until", ISO8601d (value, dateformat).toEpochString ());
} }
} }
else else
@ -581,14 +581,14 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string
if (formatted != value) if (formatted != value)
{ {
context.footnote (STRING_EDIT_WAIT_MOD); context.footnote (STRING_EDIT_WAIT_MOD);
task.set ("wait", Date(value, dateformat).toEpochString ()); task.set ("wait", ISO8601d (value, dateformat).toEpochString ());
task.setStatus (Task::waiting); task.setStatus (Task::waiting);
} }
} }
else else
{ {
context.footnote (STRING_EDIT_WAIT_MOD); context.footnote (STRING_EDIT_WAIT_MOD);
task.set ("wait", Date(value, dateformat).toEpochString ()); task.set ("wait", ISO8601d (value, dateformat).toEpochString ());
task.setStatus (Task::waiting); task.setStatus (Task::waiting);
} }
} }
@ -642,7 +642,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string
// for each line: if the annotation is the same, then it is copied; if // for each line: if the annotation is the same, then it is copied; if
// the annotation is modified, then its original date may be kept; and // the annotation is modified, then its original date may be kept; and
// if there is no corresponding id, then a new unique date is created). // if there is no corresponding id, then a new unique date is created).
Date when (value.substr (0, gap), dateformat); ISO8601d when (value.substr (0, gap), dateformat);
// If the map already contains a annotation for a given timestamp // If the map already contains a annotation for a given timestamp
// we need to increment until we find an unused key // we need to increment until we find an unused key
@ -688,7 +688,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string
{ {
std::string value = findValue (after, "\n UDA " + col.first + ":"); std::string value = findValue (after, "\n UDA " + col.first + ":");
if ((task.get (col.first) != value) && (type != "date" || if ((task.get (col.first) != value) && (type != "date" ||
(task.get (col.first) != Date (value, dateformat).toEpochString ())) && (task.get (col.first) != ISO8601d (value, dateformat).toEpochString ())) &&
(type != "duration" || (type != "duration" ||
(task.get (col.first) != (std::string) ISO8601p (value)))) (task.get (col.first) != (std::string) ISO8601p (value))))
{ {
@ -712,7 +712,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string
} }
else if (type == "date") else if (type == "date")
{ {
task.set (col.first, Date (value, dateformat).toEpochString ()); task.set (col.first, ISO8601d (value, dateformat).toEpochString ());
} }
else if (type == "duration") else if (type == "duration")
{ {

View file

@ -32,6 +32,7 @@
#include <main.h> #include <main.h>
#include <text.h> #include <text.h>
#include <i18n.h> #include <i18n.h>
#include <ISO8601.h>
#include <CmdHistory.h> #include <CmdHistory.h>
extern Context context; extern Context context;
@ -70,11 +71,11 @@ int CmdHistoryMonthly::execute (std::string& output)
for (auto& task : filtered) for (auto& task : filtered)
{ {
Date entry (task.get_date ("entry")); ISO8601d entry (task.get_date ("entry"));
Date end; ISO8601d end;
if (task.has ("end")) if (task.has ("end"))
end = Date (task.get_date ("end")); end = ISO8601d (task.get_date ("end"));
time_t epoch = entry.startOfMonth ().toEpoch (); time_t epoch = entry.startOfMonth ().toEpoch ();
groups[epoch] = 0; groups[epoch] = 0;
@ -127,7 +128,7 @@ int CmdHistoryMonthly::execute (std::string& output)
totalCompleted += completedGroup [i.first]; totalCompleted += completedGroup [i.first];
totalDeleted += deletedGroup [i.first]; totalDeleted += deletedGroup [i.first];
Date dt (i.first); ISO8601d dt (i.first);
int m, d, y; int m, d, y;
dt.toMDY (m, d, y); dt.toMDY (m, d, y);
@ -136,7 +137,7 @@ int CmdHistoryMonthly::execute (std::string& output)
view.set (row, 0, y); view.set (row, 0, y);
priorYear = y; priorYear = y;
} }
view.set (row, 1, Date::monthName(m)); view.set (row, 1, ISO8601d::monthName(m));
int net = 0; int net = 0;
@ -232,11 +233,11 @@ int CmdHistoryAnnual::execute (std::string& output)
for (auto& task : filtered) for (auto& task : filtered)
{ {
Date entry (task.get_date ("entry")); ISO8601d entry (task.get_date ("entry"));
Date end; ISO8601d end;
if (task.has ("end")) if (task.has ("end"))
end = Date (task.get_date ("end")); end = ISO8601d (task.get_date ("end"));
time_t epoch = entry.startOfYear ().toEpoch (); time_t epoch = entry.startOfYear ().toEpoch ();
groups[epoch] = 0; groups[epoch] = 0;
@ -288,7 +289,7 @@ int CmdHistoryAnnual::execute (std::string& output)
totalCompleted += completedGroup [i.first]; totalCompleted += completedGroup [i.first];
totalDeleted += deletedGroup [i.first]; totalDeleted += deletedGroup [i.first];
Date dt (i.first); ISO8601d dt (i.first);
int m, d, y; int m, d, y;
dt.toMDY (m, d, y); dt.toMDY (m, d, y);
@ -391,11 +392,11 @@ int CmdGHistoryMonthly::execute (std::string& output)
for (auto& task : filtered) for (auto& task : filtered)
{ {
Date entry (task.get_date ("entry")); ISO8601d entry (task.get_date ("entry"));
Date end; ISO8601d end;
if (task.has ("end")) if (task.has ("end"))
end = Date (task.get_date ("end")); end = ISO8601d (task.get_date ("end"));
time_t epoch = entry.startOfMonth ().toEpoch (); time_t epoch = entry.startOfMonth ().toEpoch ();
groups[epoch] = 0; groups[epoch] = 0;
@ -468,7 +469,7 @@ int CmdGHistoryMonthly::execute (std::string& output)
totalCompleted += completedGroup[i.first]; totalCompleted += completedGroup[i.first];
totalDeleted += deletedGroup[i.first]; totalDeleted += deletedGroup[i.first];
Date dt (i.first); ISO8601d dt (i.first);
int m, d, y; int m, d, y;
dt.toMDY (m, d, y); dt.toMDY (m, d, y);
@ -477,7 +478,7 @@ int CmdGHistoryMonthly::execute (std::string& output)
view.set (row, 0, y); view.set (row, 0, y);
priorYear = y; priorYear = y;
} }
view.set (row, 1, Date::monthName(m)); view.set (row, 1, ISO8601d::monthName(m));
unsigned int addedBar = (widthOfBar * addedGroup[i.first]) / maxLine; unsigned int addedBar = (widthOfBar * addedGroup[i.first]) / maxLine;
unsigned int completedBar = (widthOfBar * completedGroup[i.first]) / maxLine; unsigned int completedBar = (widthOfBar * completedGroup[i.first]) / maxLine;
@ -591,11 +592,11 @@ int CmdGHistoryAnnual::execute (std::string& output)
for (auto& task : filtered) for (auto& task : filtered)
{ {
Date entry (task.get_date ("entry")); ISO8601d entry (task.get_date ("entry"));
Date end; ISO8601d end;
if (task.has ("end")) if (task.has ("end"))
end = Date (task.get_date ("end")); end = ISO8601d (task.get_date ("end"));
time_t epoch = entry.startOfYear ().toEpoch (); time_t epoch = entry.startOfYear ().toEpoch ();
groups[epoch] = 0; groups[epoch] = 0;
@ -667,7 +668,7 @@ int CmdGHistoryAnnual::execute (std::string& output)
totalCompleted += completedGroup[i.first]; totalCompleted += completedGroup[i.first];
totalDeleted += deletedGroup[i.first]; totalDeleted += deletedGroup[i.first];
Date dt (i.first); ISO8601d dt (i.first);
int m, d, y; int m, d, y;
dt.toMDY (m, d, y); dt.toMDY (m, d, y);

View file

@ -31,7 +31,6 @@
#include <Context.h> #include <Context.h>
#include <Filter.h> #include <Filter.h>
#include <ISO8601.h> #include <ISO8601.h>
#include <Date.h>
#include <main.h> #include <main.h>
#include <text.h> #include <text.h>
#include <i18n.h> #include <i18n.h>
@ -113,7 +112,7 @@ int CmdInfo::execute (std::string& output)
view.colorHeader (label); view.colorHeader (label);
} }
Date now; ISO8601d now;
// id // id
int row = view.addRow (); int row = view.addRow ();
@ -133,7 +132,7 @@ int CmdInfo::execute (std::string& output)
for (auto& anno : annotations) for (auto& anno : annotations)
description += "\n" description += "\n"
+ std::string (indent, ' ') + std::string (indent, ' ')
+ Date (anno.first.substr (11)).toString (dateformatanno) + ISO8601d (anno.first.substr (11)).toString (dateformatanno)
+ " " + " "
+ anno.second; + anno.second;
@ -221,14 +220,14 @@ int CmdInfo::execute (std::string& output)
// entry // entry
row = view.addRow (); row = view.addRow ();
view.set (row, 0, STRING_COLUMN_LABEL_ENTERED); view.set (row, 0, STRING_COLUMN_LABEL_ENTERED);
Date dt (task.get_date ("entry")); ISO8601d dt (task.get_date ("entry"));
std::string entry = dt.toString (dateformat); std::string entry = dt.toString (dateformat);
std::string age; std::string age;
std::string created = task.get ("entry"); std::string created = task.get ("entry");
if (created.length ()) if (created.length ())
{ {
Date dt (strtol (created.c_str (), NULL, 10)); ISO8601d dt (strtol (created.c_str (), NULL, 10));
age = ISO8601p (now - dt).formatVague (); age = ISO8601p (now - dt).formatVague ();
} }
@ -239,7 +238,7 @@ int CmdInfo::execute (std::string& output)
{ {
row = view.addRow (); row = view.addRow ();
view.set (row, 0, STRING_COLUMN_LABEL_WAITING); view.set (row, 0, STRING_COLUMN_LABEL_WAITING);
view.set (row, 1, Date (task.get_date ("wait")).toString (dateformat)); view.set (row, 1, ISO8601d (task.get_date ("wait")).toString (dateformat));
} }
// scheduled // scheduled
@ -247,7 +246,7 @@ int CmdInfo::execute (std::string& output)
{ {
row = view.addRow (); row = view.addRow ();
view.set (row, 0, STRING_COLUMN_LABEL_SCHED); view.set (row, 0, STRING_COLUMN_LABEL_SCHED);
view.set (row, 1, Date (task.get_date ("scheduled")).toString (dateformat)); view.set (row, 1, ISO8601d (task.get_date ("scheduled")).toString (dateformat));
} }
// start // start
@ -255,7 +254,7 @@ int CmdInfo::execute (std::string& output)
{ {
row = view.addRow (); row = view.addRow ();
view.set (row, 0, STRING_COLUMN_LABEL_START); view.set (row, 0, STRING_COLUMN_LABEL_START);
view.set (row, 1, Date (task.get_date ("start")).toString (dateformat)); view.set (row, 1, ISO8601d (task.get_date ("start")).toString (dateformat));
} }
// due (colored) // due (colored)
@ -263,7 +262,7 @@ int CmdInfo::execute (std::string& output)
{ {
row = view.addRow (); row = view.addRow ();
view.set (row, 0, STRING_COLUMN_LABEL_DUE); view.set (row, 0, STRING_COLUMN_LABEL_DUE);
view.set (row, 1, Date (task.get_date ("due")).toString (dateformat)); view.set (row, 1, ISO8601d (task.get_date ("due")).toString (dateformat));
} }
// end // end
@ -271,7 +270,7 @@ int CmdInfo::execute (std::string& output)
{ {
row = view.addRow (); row = view.addRow ();
view.set (row, 0, STRING_COLUMN_LABEL_END); view.set (row, 0, STRING_COLUMN_LABEL_END);
view.set (row, 1, Date (task.get_date ("end")).toString (dateformat)); view.set (row, 1, ISO8601d (task.get_date ("end")).toString (dateformat));
} }
// until // until
@ -279,7 +278,7 @@ int CmdInfo::execute (std::string& output)
{ {
row = view.addRow (); row = view.addRow ();
view.set (row, 0, STRING_CMD_INFO_UNTIL); view.set (row, 0, STRING_CMD_INFO_UNTIL);
view.set (row, 1, Date (task.get_date ("until")).toString (dateformat)); view.set (row, 1, ISO8601d (task.get_date ("until")).toString (dateformat));
} }
// modified // modified
@ -288,7 +287,7 @@ int CmdInfo::execute (std::string& output)
row = view.addRow (); row = view.addRow ();
view.set (row, 0, STRING_CMD_INFO_MODIFIED); view.set (row, 0, STRING_CMD_INFO_MODIFIED);
Date mod (task.get_date ("modified")); ISO8601d mod (task.get_date ("modified"));
std::string age = ISO8601p (now - mod).formatVague (); std::string age = ISO8601p (now - mod).formatVague ();
view.set (row, 1, mod.toString (dateformat) + " (" + age + ")"); view.set (row, 1, mod.toString (dateformat) + " (" + age + ")");
} }
@ -373,13 +372,13 @@ int CmdInfo::execute (std::string& output)
view.set (row, 0, col->label ()); view.set (row, 0, col->label ());
if (type == "date") if (type == "date")
value = Date (value).toString (dateformat); value = ISO8601d (value).toString (dateformat);
else if (type == "duration") else if (type == "duration")
{ {
ISO8601p iso; ISO8601p iso;
std::string::size_type cursor = 0; std::string::size_type cursor = 0;
if (iso.parse (value, cursor)) if (iso.parse (value, cursor))
value = (std::string) Variant ((time_t) iso._value, Variant::type_duration); value = (std::string) Variant ((time_t) iso, Variant::type_duration);
else else
value = "PT0S"; value = "PT0S";
} }
@ -544,7 +543,7 @@ int CmdInfo::execute (std::string& output)
{ {
int row = journal.addRow (); int row = journal.addRow ();
Date timestamp (strtol (when.substr (5).c_str (), NULL, 10)); ISO8601d timestamp (strtol (when.substr (5).c_str (), NULL, 10));
journal.set (row, 0, timestamp.toString (dateformat)); journal.set (row, 0, timestamp.toString (dateformat));
Task before (previous.substr (4)); Task before (previous.substr (4));

View file

@ -90,7 +90,7 @@ int CmdStats::execute (std::string& output)
std::vector <Task> filtered; std::vector <Task> filtered;
filter.subset (all, filtered); filter.subset (all, filtered);
Date now; ISO8601d now;
time_t earliest = time (NULL); time_t earliest = time (NULL);
time_t latest = 1; time_t latest = 1;
int totalT = 0; int totalT = 0;
@ -235,12 +235,12 @@ int CmdStats::execute (std::string& output)
if (filtered.size ()) if (filtered.size ())
{ {
Date e (earliest); ISO8601d e (earliest);
row = view.addRow (); row = view.addRow ();
view.set (row, 0, STRING_CMD_STATS_OLDEST); view.set (row, 0, STRING_CMD_STATS_OLDEST);
view.set (row, 1, e.toString (dateformat)); view.set (row, 1, e.toString (dateformat));
Date l (latest); ISO8601d l (latest);
row = view.addRow (); row = view.addRow ();
view.set (row, 0, STRING_CMD_STATS_NEWEST); view.set (row, 0, STRING_CMD_STATS_NEWEST);
view.set (row, 1, l.toString (dateformat)); view.set (row, 1, l.toString (dateformat));

View file

@ -30,7 +30,7 @@
#include <Context.h> #include <Context.h>
#include <Filter.h> #include <Filter.h>
#include <ViewText.h> #include <ViewText.h>
#include <Date.h> #include <ISO8601.h>
#include <main.h> #include <main.h>
#include <i18n.h> #include <i18n.h>
#include <text.h> #include <text.h>
@ -64,18 +64,18 @@ int CmdTimesheet::execute (std::string& output)
std::vector <Task> all = context.tdb2.all_tasks (); std::vector <Task> all = context.tdb2.all_tasks ();
// What day of the week does the user consider the first? // What day of the week does the user consider the first?
int weekStart = Date::dayOfWeek (context.config.get ("weekstart")); int weekStart = ISO8601d::dayOfWeek (context.config.get ("weekstart"));
if (weekStart != 0 && weekStart != 1) if (weekStart != 0 && weekStart != 1)
throw std::string (STRING_DATE_BAD_WEEKSTART); throw std::string (STRING_DATE_BAD_WEEKSTART);
// Determine the date of the first day of the most recent report. // Determine the date of the first day of the most recent report.
Date today; ISO8601d today;
Date start; ISO8601d start;
start -= (((today.dayOfWeek () - weekStart) + 7) % 7) * 86400; start -= (((today.dayOfWeek () - weekStart) + 7) % 7) * 86400;
// Roll back to midnight. // Roll back to midnight.
start = Date (start.month (), start.day (), start.year ()); start = ISO8601d (start.month (), start.day (), start.year ());
Date end = start + (7 * 86400); ISO8601d end = start + (7 * 86400);
// Determine how many reports to run. // Determine how many reports to run.
int quantity = 1; int quantity = 1;
@ -86,7 +86,7 @@ int CmdTimesheet::execute (std::string& output)
std::stringstream out; std::stringstream out;
for (int week = 0; week < quantity; ++week) for (int week = 0; week < quantity; ++week)
{ {
Date endString (end); ISO8601d endString (end);
endString -= 86400; endString -= 86400;
std::string title = start.toString (context.config.get ("dateformat")) std::string title = start.toString (context.config.get ("dateformat"))
@ -114,7 +114,7 @@ int CmdTimesheet::execute (std::string& output)
// If task completed within range. // If task completed within range.
if (task.getStatus () == Task::completed) if (task.getStatus () == Task::completed)
{ {
Date compDate (task.get_date ("end")); ISO8601d compDate (task.get_date ("end"));
if (compDate >= start && compDate < end) if (compDate >= start && compDate < end)
{ {
Color c; Color c;
@ -129,7 +129,7 @@ int CmdTimesheet::execute (std::string& output)
if(task.has ("due")) if(task.has ("due"))
{ {
Date dt (task.get_date ("due")); ISO8601d dt (task.get_date ("due"));
completed.set (row, 2, dt.toString (format)); completed.set (row, 2, dt.toString (format));
} }
@ -141,7 +141,7 @@ int CmdTimesheet::execute (std::string& output)
for (auto& ann : annotations) for (auto& ann : annotations)
description += "\n" description += "\n"
+ std::string (indent, ' ') + std::string (indent, ' ')
+ Date (ann.first.substr (11)).toString (context.config.get ("dateformat")) + ISO8601d (ann.first.substr (11)).toString (context.config.get ("dateformat"))
+ " " + " "
+ ann.second; + ann.second;
@ -171,7 +171,7 @@ int CmdTimesheet::execute (std::string& output)
if (task.getStatus () == Task::pending && if (task.getStatus () == Task::pending &&
task.has ("start")) task.has ("start"))
{ {
Date startDate (task.get_date ("start")); ISO8601d startDate (task.get_date ("start"));
if (startDate >= start && startDate < end) if (startDate >= start && startDate < end)
{ {
Color c; Color c;
@ -186,7 +186,7 @@ int CmdTimesheet::execute (std::string& output)
if (task.has ("due")) if (task.has ("due"))
{ {
Date dt (task.get_date ("due")); ISO8601d dt (task.get_date ("due"));
started.set (row, 2, dt.toString (format)); started.set (row, 2, dt.toString (format));
} }
@ -198,7 +198,7 @@ int CmdTimesheet::execute (std::string& output)
for (auto& ann : annotations) for (auto& ann : annotations)
description += "\n" description += "\n"
+ std::string (indent, ' ') + std::string (indent, ' ')
+ Date (ann.first.substr (11)).toString (context.config.get ("dateformat")) + ISO8601d (ann.first.substr (11)).toString (context.config.get ("dateformat"))
+ " " + " "
+ ann.second; + ann.second;

View file

@ -266,16 +266,12 @@ std::string renderAttribute (const std::string& name, const std::string& value,
col->type () == "date" && col->type () == "date" &&
value != "") value != "")
{ {
Date d ((time_t)strtol (value.c_str (), NULL, 10)); ISO8601d d ((time_t)strtol (value.c_str (), NULL, 10));
if (format == "") if (format == "")
{
return d.toString (context.config.get ("dateformat")); return d.toString (context.config.get ("dateformat"));
}
else
{
return d.toString (format); return d.toString (format);
} }
}
return value; return value;
} }

View file

@ -32,13 +32,13 @@
#include <map> #include <map>
#include <sys/types.h> #include <sys/types.h>
#include <Context.h> #include <Context.h>
#include <Date.h> #include <ISO8601.h>
#include <Color.h> #include <Color.h>
// recur.cpp // recur.cpp
void handleRecurrence (); void handleRecurrence ();
Date getNextRecurrence (Date&, std::string&); ISO8601d getNextRecurrence (ISO8601d&, std::string&);
bool generateDueDates (Task&, std::vector <Date>&); bool generateDueDates (Task&, std::vector <ISO8601d>&);
void updateRecurrenceMask (Task&); void updateRecurrenceMask (Task&);
bool nag (Task&); bool nag (Task&);

View file

@ -39,8 +39,6 @@
#include <time.h> #include <time.h>
#include <Context.h> #include <Context.h>
#include <Date.h>
#include <ISO8601.h>
#include <Lexer.h> #include <Lexer.h>
#include <ISO8601.h> #include <ISO8601.h>
#include <text.h> #include <text.h>
@ -62,7 +60,7 @@ void handleRecurrence ()
return; return;
auto tasks = context.tdb2.pending.get_tasks (); auto tasks = context.tdb2.pending.get_tasks ();
Date now; ISO8601d now;
// Look at all tasks and find any recurring ones. // Look at all tasks and find any recurring ones.
for (auto& t : tasks) for (auto& t : tasks)
@ -71,7 +69,7 @@ void handleRecurrence ()
{ {
// Generate a list of due dates for this recurring task, regardless of // Generate a list of due dates for this recurring task, regardless of
// the mask. // the mask.
std::vector <Date> due; std::vector <ISO8601d> due;
if (!generateDueDates (t, due)) if (!generateDueDates (t, due))
{ {
// Determine the end date. // Determine the end date.
@ -106,9 +104,9 @@ void handleRecurrence ()
if (t.has ("wait")) if (t.has ("wait"))
{ {
Date old_wait (t.get_date ("wait")); ISO8601d old_wait (t.get_date ("wait"));
Date old_due (t.get_date ("due")); ISO8601d old_due (t.get_date ("due"));
Date due (d); ISO8601d due (d);
sprintf (dueDate, "%u", (unsigned int) (due + (old_wait - old_due)).toEpoch ()); sprintf (dueDate, "%u", (unsigned int) (due + (old_wait - old_due)).toEpoch ());
rec.set ("wait", dueDate); rec.set ("wait", dueDate);
rec.setStatus (Task::waiting); rec.setStatus (Task::waiting);
@ -148,7 +146,7 @@ void handleRecurrence ()
else else
{ {
if (t.has ("until") && if (t.has ("until") &&
Date (t.get_date ("until")) < now) ISO8601d (t.get_date ("until")) < now)
{ {
t.setStatus (Task::deleted); t.setStatus (Task::deleted);
context.tdb2.modify(t); context.tdb2.modify(t);
@ -163,28 +161,28 @@ void handleRecurrence ()
// period (recur). Then generate a set of corresponding dates. // period (recur). Then generate a set of corresponding dates.
// //
// Returns false if the parent recurring task is depleted. // Returns false if the parent recurring task is depleted.
bool generateDueDates (Task& parent, std::vector <Date>& allDue) bool generateDueDates (Task& parent, std::vector <ISO8601d>& allDue)
{ {
// Determine due date, recur period and until date. // Determine due date, recur period and until date.
Date due (parent.get_date ("due")); ISO8601d due (parent.get_date ("due"));
if (due == 0) if (due._date == 0)
{ {
return false; return false;
} }
std::string recur = parent.get ("recur"); std::string recur = parent.get ("recur");
bool specificEnd = false; bool specificEnd = false;
Date until; ISO8601d until;
if (parent.get ("until") != "") if (parent.get ("until") != "")
{ {
until = Date (parent.get ("until")); until = ISO8601d (parent.get ("until"));
specificEnd = true; specificEnd = true;
} }
int recurrence_limit = context.config.getInteger ("recurrence.limit"); int recurrence_limit = context.config.getInteger ("recurrence.limit");
int recurrence_counter = 0; int recurrence_counter = 0;
Date now; ISO8601d now;
for (Date i = due; ; i = getNextRecurrence (i, recur)) for (ISO8601d i = due; ; i = getNextRecurrence (i, recur))
{ {
allDue.push_back (i); allDue.push_back (i);
@ -212,7 +210,7 @@ bool generateDueDates (Task& parent, std::vector <Date>& allDue)
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
Date getNextRecurrence (Date& current, std::string& period) ISO8601d getNextRecurrence (ISO8601d& current, std::string& period)
{ {
int m = current.month (); int m = current.month ();
int d = current.day (); int d = current.day ();
@ -228,10 +226,10 @@ Date getNextRecurrence (Date& current, std::string& period)
++y; ++y;
} }
while (! Date::valid (m, d, y)) while (! ISO8601d::valid (m, d, y))
--d; --d;
return Date (m, d, y); return ISO8601d (m, d, y);
} }
else if (period == "weekdays") else if (period == "weekdays")
@ -258,10 +256,10 @@ Date getNextRecurrence (Date& current, std::string& period)
++y; ++y;
} }
while (! Date::valid (m, d, y)) while (! ISO8601d::valid (m, d, y))
--d; --d;
return Date (m, d, y); return ISO8601d (m, d, y);
} }
else if (period[0] == 'P' && else if (period[0] == 'P' &&
@ -277,10 +275,10 @@ Date getNextRecurrence (Date& current, std::string& period)
++y; ++y;
} }
while (! Date::valid (m, d, y)) while (! ISO8601d::valid (m, d, y))
--d; --d;
return Date (m, d, y); return ISO8601d (m, d, y);
} }
else if (period == "quarterly" || else if (period == "quarterly" ||
@ -293,10 +291,10 @@ Date getNextRecurrence (Date& current, std::string& period)
++y; ++y;
} }
while (! Date::valid (m, d, y)) while (! ISO8601d::valid (m, d, y))
--d; --d;
return Date (m, d, y); return ISO8601d (m, d, y);
} }
else if (Lexer::isDigit (period[0]) && period[period.length () - 1] == 'q') else if (Lexer::isDigit (period[0]) && period[period.length () - 1] == 'q')
@ -310,10 +308,10 @@ Date getNextRecurrence (Date& current, std::string& period)
++y; ++y;
} }
while (! Date::valid (m, d, y)) while (! ISO8601d::valid (m, d, y))
--d; --d;
return Date (m, d, y); return ISO8601d (m, d, y);
} }
else if (period == "semiannual" || else if (period == "semiannual" ||
@ -326,10 +324,10 @@ Date getNextRecurrence (Date& current, std::string& period)
++y; ++y;
} }
while (! Date::valid (m, d, y)) while (! ISO8601d::valid (m, d, y))
--d; --d;
return Date (m, d, y); return ISO8601d (m, d, y);
} }
else if (period == "bimonthly" || else if (period == "bimonthly" ||
@ -342,10 +340,10 @@ Date getNextRecurrence (Date& current, std::string& period)
++y; ++y;
} }
while (! Date::valid (m, d, y)) while (! ISO8601d::valid (m, d, y))
--d; --d;
return Date (m, d, y); return ISO8601d (m, d, y);
} }
else if (period == "biannual" || else if (period == "biannual" ||
@ -354,7 +352,7 @@ Date getNextRecurrence (Date& current, std::string& period)
{ {
y += 2; y += 2;
return Date (m, d, y); return ISO8601d (m, d, y);
} }
else if (period == "annual" || else if (period == "annual" ||
@ -368,7 +366,7 @@ Date getNextRecurrence (Date& current, std::string& period)
if (m == 2 && d == 29) if (m == 2 && d == 29)
d = 28; d = 28;
return Date (m, d, y); return ISO8601d (m, d, y);
} }
// Add the period to current, and we're done. // Add the period to current, and we're done.

View file

@ -27,7 +27,7 @@
#include <cmake.h> #include <cmake.h>
#include <stdlib.h> #include <stdlib.h>
#include <Context.h> #include <Context.h>
#include <Date.h> #include <ISO8601.h>
#include <text.h> #include <text.h>
#include <util.h> #include <util.h>
#include <main.h> #include <main.h>
@ -36,7 +36,7 @@ extern Context context;
static std::map <std::string, Color> gsColor; static std::map <std::string, Color> gsColor;
static std::vector <std::string> gsPrecedence; static std::vector <std::string> gsPrecedence;
static Date now; static ISO8601d now;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void initializeColorRules () void initializeColorRules ()
@ -130,7 +130,7 @@ static void colorizeActive (Task& task, const Color& base, Color& c, bool merge)
static void colorizeScheduled (Task& task, const Color& base, Color& c, bool merge) static void colorizeScheduled (Task& task, const Color& base, Color& c, bool merge)
{ {
if (task.has ("scheduled") && if (task.has ("scheduled") &&
Date (task.get_date ("scheduled")) <= now) ISO8601d (task.get_date ("scheduled")) <= now)
applyColor (base, c, merge); applyColor (base, c, merge);
} }

View file

@ -51,7 +51,6 @@
#include <signal.h> #include <signal.h>
#include <sys/select.h> #include <sys/select.h>
#include <Date.h>
#include <text.h> #include <text.h>
#include <main.h> #include <main.h>
#include <i18n.h> #include <i18n.h>

1
test/.gitignore vendored
View file

@ -7,7 +7,6 @@ autocomplete.t
col.t col.t
color.t color.t
config.t config.t
date.t
dates.t dates.t
eval.t eval.t
fs.t fs.t

View file

@ -9,15 +9,15 @@ include_directories (${CMAKE_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/test ${CMAKE_SOURCE_DIR}/test
${TASK_INCLUDE_DIRS}) ${TASK_INCLUDE_DIRS})
set (test_SRCS autocomplete.t col.t color.t config.t date.t fs.t i18n.t json.t set (test_SRCS autocomplete.t col.t color.t config.t fs.t i18n.t json.t list.t
list.t msg.t nibbler.t rx.t t.t t2.t t3.t tdb2.t text.t utf8.t msg.t nibbler.t rx.t t.t t2.t t3.t tdb2.t text.t utf8.t util.t
util.t view.t json_test lexer.t iso8601d.t iso8601p.t eval.t view.t json_test lexer.t iso8601d.t iso8601p.t eval.t dates.t
variant_add.t variant_and.t variant_cast.t variant_divide.t variant_add.t variant_and.t variant_cast.t variant_divide.t
variant_equal.t variant_exp.t variant_gt.t variant_gte.t variant_equal.t variant_exp.t variant_gt.t variant_gte.t
variant_inequal.t variant_lt.t variant_lte.t variant_match.t variant_inequal.t variant_lt.t variant_lte.t variant_match.t
variant_math.t variant_modulo.t variant_multiply.t variant_math.t variant_modulo.t variant_multiply.t
variant_nomatch.t variant_not.t variant_or.t variant_partial.t variant_nomatch.t variant_not.t variant_or.t variant_partial.t
variant_subtract.t variant_xor.t dates.t) variant_subtract.t variant_xor.t)
add_custom_target (test ./run_all --verbose add_custom_target (test ./run_all --verbose
DEPENDS ${test_SRCS} task_executable DEPENDS ${test_SRCS} task_executable

View file

@ -1,461 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////
#include <cmake.h>
#include <iostream>
#include <stdlib.h>
#include <Context.h>
#include <Date.h>
#include <test.h>
Context context;
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
UnitTest t (211);
// Ensure environment has no influence.
unsetenv ("TASKDATA");
unsetenv ("TASKRC");
try
{
Date now;
Date yesterday;
yesterday -= 86400;
Date tomorrow;
tomorrow += 86400;
t.ok (yesterday <= now, "yesterday <= now");
t.ok (yesterday < now, "yesterday < now");
t.notok (yesterday == now, "!(yesterday == now)");
t.ok (yesterday != now, "yesterday != now");
t.ok (now >= yesterday, "now >= yesterday");
t.ok (now > yesterday, "now > yesterday");
t.ok (tomorrow >= now, "tomorrow >= now");
t.ok (tomorrow > now, "tomorrow > now");
t.notok (tomorrow == now, "!(tomorrow == now)");
t.ok (tomorrow != now, "tomorrow != now");
t.ok (now <= tomorrow, "now <= tomorrow");
t.ok (now < tomorrow, "now < tomorrow");
// Date::Date ("now")
context.config.set ("weekstart", "monday");
Date relative_now ("now");
t.ok (relative_now.sameHour (now), "Date ().sameHour (Date (now))");
t.ok (relative_now.sameDay (now), "Date ().sameDay (Date (now))");
t.ok (relative_now.sameWeek (now), "Date ().sameWeek (Date (now))");
t.ok (relative_now.sameMonth (now), "Date ().sameMonth (Date (now))");
t.ok (relative_now.sameYear (now), "Date ().sameYear (Date (now))");
// Loose comparisons.
Date left ("7/4/2008");
Date comp1 ("7/4/2008");
t.ok (left.sameDay (comp1), "7/4/2008 is on the same day as 7/4/2008");
t.ok (left.sameWeek (comp1), "7/4/2008 is on the same week as 7/4/2008");
t.ok (left.sameMonth (comp1), "7/4/2008 is in the same month as 7/4/2008");
t.ok (left.sameYear (comp1), "7/4/2008 is in the same year as 7/4/2008");
Date comp2 ("7/5/2008");
t.notok (left.sameDay (comp2), "7/4/2008 is not on the same day as 7/5/2008");
t.ok (left.sameMonth (comp2), "7/4/2008 is in the same month as 7/5/2008");
t.ok (left.sameYear (comp2), "7/4/2008 is in the same year as 7/5/2008");
Date comp3 ("8/4/2008");
t.notok (left.sameDay (comp3), "7/4/2008 is not on the same day as 8/4/2008");
t.notok (left.sameWeek (comp3), "7/4/2008 is not on the same week as 8/4/2008");
t.notok (left.sameMonth (comp3), "7/4/2008 is not in the same month as 8/4/2008");
t.ok (left.sameYear (comp3), "7/4/2008 is in the same year as 8/4/2008");
Date comp4 ("7/4/2009");
t.notok (left.sameDay (comp4), "7/4/2008 is not on the same day as 7/4/2009");
t.notok (left.sameWeek (comp3), "7/4/2008 is not on the same week as 7/4/2009");
t.notok (left.sameMonth (comp4), "7/4/2008 is not in the same month as 7/4/2009");
t.notok (left.sameYear (comp4), "7/4/2008 is not in the same year as 7/4/2009");
// Validity.
t.ok (Date::valid (2, 29, 2008), "valid: 2/29/2008");
t.notok (Date::valid (2, 29, 2007), "invalid: 2/29/2007");
t.ok (Date::valid ("2/29/2008"), "valid: 2/29/2008");
t.notok (Date::valid ("2/29/2007"), "invalid: 2/29/2007");
t.ok (Date::valid (366, 2008), "valid: 366 days in 2008");
t.notok (Date::valid (366, 2007), "invalid: 366 days in 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");
t.ok (Date::leapYear (2000), "2000 is a leap year");
t.notok (Date::leapYear (1900), "1900 is not a leap year");
// Days in month.
t.is (Date::daysInMonth (2, 2008), 29, "29 days in February 2008");
t.is (Date::daysInMonth (2, 2007), 28, "28 days in February 2007");
// Names.
t.is (Date::monthName (1), "January", "1 = January");
t.is (Date::monthName (2), "February", "2 = February");
t.is (Date::monthName (3), "March", "3 = March");
t.is (Date::monthName (4), "April", "4 = April");
t.is (Date::monthName (5), "May", "5 = May");
t.is (Date::monthName (6), "June", "6 = June");
t.is (Date::monthName (7), "July", "7 = July");
t.is (Date::monthName (8), "August", "8 = August");
t.is (Date::monthName (9), "September", "9 = September");
t.is (Date::monthName (10), "October", "10 = October");
t.is (Date::monthName (11), "November", "11 = November");
t.is (Date::monthName (12), "December", "12 = December");
t.is (Date::dayName (0), "Sunday", "0 == Sunday");
t.is (Date::dayName (1), "Monday", "1 == Monday");
t.is (Date::dayName (2), "Tuesday", "2 == Tuesday");
t.is (Date::dayName (3), "Wednesday", "3 == Wednesday");
t.is (Date::dayName (4), "Thursday", "4 == Thursday");
t.is (Date::dayName (5), "Friday", "5 == Friday");
t.is (Date::dayName (6), "Saturday", "6 == Saturday");
t.is (Date::dayOfWeek ("SUNDAY"), 0, "SUNDAY == 0");
t.is (Date::dayOfWeek ("sunday"), 0, "sunday == 0");
t.is (Date::dayOfWeek ("Sunday"), 0, "Sunday == 0");
t.is (Date::dayOfWeek ("Monday"), 1, "Monday == 1");
t.is (Date::dayOfWeek ("Tuesday"), 2, "Tuesday == 2");
t.is (Date::dayOfWeek ("Wednesday"), 3, "Wednesday == 3");
t.is (Date::dayOfWeek ("Thursday"), 4, "Thursday == 4");
t.is (Date::dayOfWeek ("Friday"), 5, "Friday == 5");
t.is (Date::dayOfWeek ("Saturday"), 6, "Saturday == 6");
Date happyNewYear (1, 1, 2008);
t.is (happyNewYear.dayOfWeek (), 2, "1/1/2008 == Tuesday");
t.is (happyNewYear.month (), 1, "1/1/2008 == January");
t.is (happyNewYear.day (), 1, "1/1/2008 == 1");
t.is (happyNewYear.year (), 2008, "1/1/2008 == 2008");
t.is (happyNewYear.toString (), "1/1/2008", "toString 1/1/2008");
int m, d, y;
happyNewYear.toMDY (m, d, y);
t.is (m, 1, "1/1/2008 == January");
t.is (d, 1, "1/1/2008 == 1");
t.is (y, 2008, "1/1/2008 == 2008");
Date epoch (9, 8, 2001);
t.ok ((int)epoch.toEpoch () < 1000000000, "9/8/2001 < 1,000,000,000");
epoch += 172800;
t.ok ((int)epoch.toEpoch () > 1000000000, "9/10/2001 > 1,000,000,000");
Date fromEpoch (epoch.toEpoch ());
t.is (fromEpoch.toString (), epoch.toString (), "ctor (time_t)");
Date iso (1000000000);
t.is (iso.toISO (), "20010909T014640Z", "1,000,000,000 -> 20010909T014640Z");
// Quantization.
Date quant (1234526400);
t.is (quant.startOfDay ().toString ("YMDHNS"), "20090213000000", "1234526400 -> 2/13/2009 12:00:00 UTC -> 2/13/2009 0:00:00");
t.is (quant.startOfWeek ().toString ("YMDHNS"), "20090208000000", "1234526400 -> 2/13/2009 12:00:00 UTC -> 2/8/2009 0:00:00");
t.is (quant.startOfMonth ().toString ("YMDHNS"), "20090201000000", "1234526400 -> 2/13/2009 12:00:00 UTC -> 2/1/2009 0:00:00");
t.is (quant.startOfYear ().toString ("YMDHNS"), "20090101000000", "1234526400 -> 2/13/2009 12:00:00 UTC -> 1/1/2009 0:00:00");
// Date parsing.
Date fromString1 ("1/1/2008");
t.is (fromString1.month (), 1, "ctor (std::string) -> m");
t.is (fromString1.day (), 1, "ctor (std::string) -> d");
t.is (fromString1.year (), 2008, "ctor (std::string) -> y");
Date fromString2 ("1/1/2008", "m/d/Y");
t.is (fromString2.month (), 1, "ctor (std::string) -> m");
t.is (fromString2.day (), 1, "ctor (std::string) -> d");
t.is (fromString2.year (), 2008, "ctor (std::string) -> y");
Date fromString3 ("20080101", "YMD");
t.is (fromString3.month (), 1, "ctor (std::string) -> m");
t.is (fromString3.day (), 1, "ctor (std::string) -> d");
t.is (fromString3.year (), 2008, "ctor (std::string) -> y");
Date fromString4 ("12/31/2007");
t.is (fromString4.month (), 12, "ctor (std::string) -> m");
t.is (fromString4.day (), 31, "ctor (std::string) -> d");
t.is (fromString4.year (), 2007, "ctor (std::string) -> y");
Date fromString5 ("12/31/2007", "m/d/Y");
t.is (fromString5.month (), 12, "ctor (std::string) -> m");
t.is (fromString5.day (), 31, "ctor (std::string) -> d");
t.is (fromString5.year (), 2007, "ctor (std::string) -> y");
Date fromString6 ("20071231", "YMD");
t.is (fromString6.month (), 12, "ctor (std::string) -> m");
t.is (fromString6.day (), 31, "ctor (std::string) -> d");
t.is (fromString6.year (), 2007, "ctor (std::string) -> y");
Date fromString7 ("01/01/2008", "m/d/Y");
t.is (fromString7.month (), 1, "ctor (std::string) -> m");
t.is (fromString7.day (), 1, "ctor (std::string) -> d");
t.is (fromString7.year (), 2008, "ctor (std::string) -> y");
Date fromString8 ("Tue 05 Feb 2008 (06)", "a D b Y (V)");
t.is (fromString8.month (), 2, "ctor (std::string) -> m");
t.is (fromString8.day (), 5, "ctor (std::string) -> d");
t.is (fromString8.year (), 2008, "ctor (std::string) -> y");
Date fromString9 ("Tuesday, February 5, 2008", "A, B d, Y");
t.is (fromString9.month (), 2, "ctor (std::string) -> m");
t.is (fromString9.day (), 5, "ctor (std::string) -> d");
t.is (fromString9.year (), 2008, "ctor (std::string) -> y");
Date fromString10 ("w01 Tue 2008-01-01", "wV a Y-M-D");
t.is (fromString10.month (), 1, "ctor (std::string) -> m");
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");
// Day of year
t.is (Date ("1/1/2011", "m/d/Y").dayOfYear (), 1, "dayOfYear (1/1/2011) -> 1");
t.is (Date ("5/1/2011", "m/d/Y").dayOfYear (), 121, "dayOfYear (5/1/2011) -> 121");
t.is (Date ("12/31/2011", "m/d/Y").dayOfYear (), 365, "dayOfYear (12/31/2011) -> 365");
// Easter
Date e1 (Date::easter(1980));
t.is (e1.toString (), "4/6/1980", "Easter 4/6/1980");
Date e2 (Date::easter(1995));
t.is (e2.toString (), "4/16/1995", "Easter 4/16/1995");
Date e3 (Date::easter(2000));
t.is (e3.toString (), "4/23/2000", "Easter 4/23/2000");
Date e4 (Date::easter(2009));
t.is (e4.toString (), "4/12/2009", "Easter 4/12/2009");
Date e5 (Date::easter(2010));
t.is (e5.toString (), "4/4/2010", "Easter 4/4/2010");
Date e6 (Date::easter(2011));
t.is (e6.toString (), "4/24/2011", "Easter 4/24/2011");
Date e7 (Date::easter(2012));
t.is (e7.toString (), "4/8/2012", "Easter 4/8/2012");
Date e8 (Date::easter(2020));
t.is (e8.toString (), "4/12/2020", "Easter 4/12/2020");
// Relative dates.
Date r1 ("today");
t.ok (r1.sameDay (now), "today = now");
Date r4 ("sunday");
if (now.dayOfWeek () >= 0)
t.ok (r4.sameDay (now + (0 - now.dayOfWeek () + 7) * 86400), "next sunday");
else
t.ok (r4.sameDay (now + (0 - now.dayOfWeek ()) * 86400), "next sunday");;
Date r5 ("monday");
if (now.dayOfWeek () >= 1)
t.ok (r5.sameDay (now + (1 - now.dayOfWeek () + 7) * 86400), "next monday");
else
t.ok (r5.sameDay (now + (1 - now.dayOfWeek ()) * 86400), "next monday");;
Date r6 ("tuesday");
if (now.dayOfWeek () >= 2)
t.ok (r6.sameDay (now + (2 - now.dayOfWeek () + 7) * 86400), "next tuesday");
else
t.ok (r6.sameDay (now + (2 - now.dayOfWeek ()) * 86400), "next tuesday");;
Date r7 ("wednesday");
if (now.dayOfWeek () >= 3)
t.ok (r7.sameDay (now + (3 - now.dayOfWeek () + 7) * 86400), "next wednesday");
else
t.ok (r7.sameDay (now + (3 - now.dayOfWeek ()) * 86400), "next wednesday");;
Date r8 ("thursday");
if (now.dayOfWeek () >= 4)
t.ok (r8.sameDay (now + (4 - now.dayOfWeek () + 7) * 86400), "next thursday");
else
t.ok (r8.sameDay (now + (4 - now.dayOfWeek ()) * 86400), "next thursday");;
Date r9 ("friday");
if (now.dayOfWeek () >= 5)
t.ok (r9.sameDay (now + (5 - now.dayOfWeek () + 7) * 86400), "next friday");
else
t.ok (r9.sameDay (now + (5 - now.dayOfWeek ()) * 86400), "next friday");;
Date r10 ("saturday");
if (now.dayOfWeek () >= 6)
t.ok (r10.sameDay (now + (6 - now.dayOfWeek () + 7) * 86400), "next saturday");
else
t.ok (r10.sameDay (now + (6 - now.dayOfWeek ()) * 86400), "next saturday");;
Date r11 ("eow");
t.ok (r11 < now + (8 * 86400), "eow < 7 days away");
Date r12 ("eocw");
t.ok (r12 > now - (8 * 86400), "eocw < 7 days in the past");
Date r13 ("eom");
t.ok (r13.sameMonth (now), "eom in same month as now");
Date r14 ("eocm");
t.ok (r14.sameMonth (now), "eocm in same month as now");
Date r15 ("eoy");
t.ok (r15.sameYear (now), "eoy in same year as now");
Date r16 ("sow");
t.ok (r16 < now + (8 * 86400), "sow < 7 days away");
Date r23 ("socw");
t.ok (r23 > now - (8 * 86400), "sow < 7 days in the past");
Date r17 ("som");
t.notok (r17.sameMonth (now), "som not in same month as now");
Date r18 ("socm");
t.ok (r18.sameMonth (now), "socm in same month as now");
Date r19 ("soy");
t.notok (r19.sameYear (now), "soy not in same year as now");
Date first ("1st");
t.notok (first.sameMonth (now), "1st not in same month as now");
t.is (first.day (), 1, "1st day is 1");
Date later ("later");
t.is (later.month (), 1, "later -> m = 1");
t.is (later.day (), 18, "later -> d = 18");
t.is (later.year (), 2038, "later -> y = 2038");
// Quarters
Date soq ("soq");
Date eoq ("eoq");
t.is (soq.day (), 1, "soq is the first day of a month");
t.is (eoq.day () / 10, 3, "eoq is the 30th or 31th of a month");
t.is (soq.month () % 3, 1, "soq month is 1, 4, 7 or 10");
t.is (eoq.month () % 3, 0, "eoq month is 3, 6, 9 or 12");
// Note: these fail during the night of daylight savings end.
t.ok (soq.sameYear (now) ||
(now.month () >= 10 &&
soq.year () == now.year () + 1), "soq is in same year as now");
t.ok (eoq.sameYear (now), "eoq is in same year as now");
// Date::sameHour
Date r20 ("6/7/2010 01:00:00", "m/d/Y H:N:S");
Date r21 ("6/7/2010 01:59:59", "m/d/Y H:N:S");
t.ok (r20.sameHour (r21), "two dates within the same hour");
Date r22 ("6/7/2010 00:59:59", "m/d/Y H:N:S");
t.notok (r20.sameHour (r22), "two dates not within the same hour");
// Date::operator-
Date r25 (1234567890);
t.is ((r25 - 1).toEpoch (), 1234567889, "1234567890 - 1 = 1234567889");
// Date::operator--
Date r26 (11, 7, 2010, 23, 59, 59);
r26--;
t.is (r26.toString ("YMDHNS"), "20101106235959", "decrement across fall DST boundary");
Date r27 (3, 14, 2010, 23, 59, 59);
r27--;
t.is (r27.toString ("YMDHNS"), "20100313235959", "decrement across spring DST boundary");
// Date::operator++
Date r28 (11, 6, 2010, 23, 59, 59);
r28++;
t.is (r28.toString ("YMDHNS"), "20101107235959", "increment across fall DST boundary");
Date r29 (3, 13, 2010, 23, 59, 59);
r29++;
t.is (r29.toString ("YMDHNS"), "20100314235959", "increment across spring DST boundary");
// int Date::length (const std::string&);
t.is (Date::length ("m"), 2, "length 'm' --> 2");
t.is (Date::length ("M"), 2, "length 'M' --> 2");
t.is (Date::length ("d"), 2, "length 'd' --> 2");
t.is (Date::length ("D"), 2, "length 'D' --> 2");
t.is (Date::length ("y"), 2, "length 'y' --> 2");
t.is (Date::length ("Y"), 4, "length 'Y' --> 4");
t.is (Date::length ("a"), 3, "length 'a' --> 3");
t.is (Date::length ("A"), 10, "length 'A' --> 10");
t.is (Date::length ("b"), 3, "length 'b' --> 3");
t.is (Date::length ("B"), 10, "length 'B' --> 10");
t.is (Date::length ("v"), 2, "length 'v' --> 2");
t.is (Date::length ("V"), 2, "length 'V' --> 2");
t.is (Date::length ("h"), 2, "length 'h' --> 2");
t.is (Date::length ("H"), 2, "length 'H' --> 2");
t.is (Date::length ("n"), 2, "length 'n' --> 2");
t.is (Date::length ("N"), 2, "length 'N' --> 2");
t.is (Date::length ("s"), 2, "length 's' --> 2");
t.is (Date::length ("S"), 2, "length 'S' --> 2");
t.is (Date::length ("j"), 3, "length 'j' --> 3");
t.is (Date::length ("J"), 3, "length 'J' --> 3");
t.is (Date::length (" "), 1, "length ' ' --> 1");
// Depletion requirement.
Date r30 ("Mon Jun 30 2014", "a b D Y", false, false);
t.is (r30.toString ("YMDHNS"), "20140630000000", "Depletion required on complex format with spaces");
std::string::size_type i = 0;
Date r31 ("Mon Jun 30 2014 xxx", i, "a b D Y", false, false);
t.is (r31.toString ("YMDHNS"), "20140630000000", "Depletion not required on complex format with spaces");
t.is ((int)i, 15, "Depletion not required on complex format with spaces, 15 chars");
}
catch (const std::string& e)
{
t.fail ("Exception thrown.");
t.diag (e);
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -47,7 +47,7 @@ void testParse (
int in_seconds, int in_seconds,
int in_offset, int in_offset,
bool in_utc, bool in_utc,
time_t in_value) time_t in_date)
{ {
std::string label = std::string ("parse (\"") + input + "\") --> "; std::string label = std::string ("parse (\"") + input + "\") --> ";
@ -65,13 +65,13 @@ void testParse (
t.is (iso._seconds, in_seconds, label + "_seconds"); t.is (iso._seconds, in_seconds, label + "_seconds");
t.is (iso._offset, in_offset, label + "_offset"); t.is (iso._offset, in_offset, label + "_offset");
t.is (iso._utc, in_utc, label + "_utc"); t.is (iso._utc, in_utc, label + "_utc");
t.is ((size_t) iso._value, (size_t) in_value, label + "_value"); t.is ((size_t) iso._date, (size_t) in_date, label + "_date");
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv) int main (int argc, char** argv)
{ {
UnitTest t (758); UnitTest t (904);
ISO8601d iso; ISO8601d iso;
std::string::size_type start = 0; std::string::size_type start = 0;
@ -216,6 +216,412 @@ int main (int argc, char** argv)
testParse (t, "20131206T123456Z", 16, 2013, 12, 0, 0, 0, 6, hms, 0, true, utc6+hms ); testParse (t, "20131206T123456Z", 16, 2013, 12, 0, 0, 0, 6, hms, 0, true, utc6+hms );
testParse (t, "20131206T123456", 15, 2013, 12, 0, 0, 0, 6, hms, 0, false, local6+hms); testParse (t, "20131206T123456", 15, 2013, 12, 0, 0, 0, 6, hms, 0, false, local6+hms);
try
{
ISO8601d now;
t.ok (now.toISO ().find ("1969") == std::string::npos, "'now' != 1969");
ISO8601d yesterday;
yesterday -= 86400;
ISO8601d tomorrow;
tomorrow += 86400;
t.ok (yesterday <= now, "yesterday <= now");
t.ok (yesterday < now, "yesterday < now");
t.notok (yesterday == now, "!(yesterday == now)");
t.ok (yesterday != now, "yesterday != now");
t.ok (now >= yesterday, "now >= yesterday");
t.ok (now > yesterday, "now > yesterday");
t.ok (tomorrow >= now, "tomorrow >= now");
t.ok (tomorrow > now, "tomorrow > now");
t.notok (tomorrow == now, "!(tomorrow == now)");
t.ok (tomorrow != now, "tomorrow != now");
t.ok (now <= tomorrow, "now <= tomorrow");
t.ok (now < tomorrow, "now < tomorrow");
// Date::Date ("now")
context.config.set ("weekstart", "monday");
ISO8601d relative_now;
t.ok (relative_now.sameHour (now), "ISO8601d ().sameHour (ISO8601d (now))");
t.ok (relative_now.sameDay (now), "ISO8601d ().sameDay (ISO8601d (now))");
t.ok (relative_now.sameWeek (now), "ISO8601d ().sameWeek (ISO8601d (now))");
t.ok (relative_now.sameMonth (now), "ISO8601d ().sameMonth (ISO8601d (now))");
t.ok (relative_now.sameYear (now), "ISO8601d ().sameYear (ISO8601d (now))");
// Loose comparisons.
ISO8601d left ("7/4/2008", "m/d/Y");
ISO8601d comp1 ("7/4/2008", "m/d/Y");
t.ok (left.sameDay (comp1), "7/4/2008 is on the same day as 7/4/2008");
t.ok (left.sameWeek (comp1), "7/4/2008 is on the same week as 7/4/2008");
t.ok (left.sameMonth (comp1), "7/4/2008 is in the same month as 7/4/2008");
t.ok (left.sameYear (comp1), "7/4/2008 is in the same year as 7/4/2008");
ISO8601d comp2 ("7/5/2008", "m/d/Y");
t.notok (left.sameDay (comp2), "7/4/2008 is not on the same day as 7/5/2008");
t.ok (left.sameMonth (comp2), "7/4/2008 is in the same month as 7/5/2008");
t.ok (left.sameYear (comp2), "7/4/2008 is in the same year as 7/5/2008");
ISO8601d comp3 ("8/4/2008", "m/d/Y");
t.notok (left.sameDay (comp3), "7/4/2008 is not on the same day as 8/4/2008");
t.notok (left.sameWeek (comp3), "7/4/2008 is not on the same week as 8/4/2008");
t.notok (left.sameMonth (comp3), "7/4/2008 is not in the same month as 8/4/2008");
t.ok (left.sameYear (comp3), "7/4/2008 is in the same year as 8/4/2008");
ISO8601d comp4 ("7/4/2009", "m/d/Y");
t.notok (left.sameDay (comp4), "7/4/2008 is not on the same day as 7/4/2009");
t.notok (left.sameWeek (comp3), "7/4/2008 is not on the same week as 7/4/2009");
t.notok (left.sameMonth (comp4), "7/4/2008 is not in the same month as 7/4/2009");
t.notok (left.sameYear (comp4), "7/4/2008 is not in the same year as 7/4/2009");
// Validity.
t.ok (ISO8601d::valid (2, 29, 2008), "valid: 2/29/2008");
t.notok (ISO8601d::valid (2, 29, 2007), "invalid: 2/29/2007");
t.ok (ISO8601d::valid ("2/29/2008", "m/d/Y"), "valid: 2/29/2008");
t.notok (ISO8601d::valid ("2/29/2007", "m/d/Y"), "invalid: 2/29/2007");
t.ok (ISO8601d::valid (366, 2008), "valid: 366 days in 2008");
t.notok (ISO8601d::valid (366, 2007), "invalid: 366 days in 2007");
// Time validity.
t.ok (ISO8601d::valid (2, 28, 2010, 0, 0, 0), "valid 2/28/2010 0:00:00");
t.ok (ISO8601d::valid (2, 28, 2010, 23, 59, 59), "valid 2/28/2010 23:59:59");
t.notok (ISO8601d::valid (2, 28, 2010, 24, 59, 59), "valid 2/28/2010 24:59:59");
t.notok (ISO8601d::valid (2, 28, 2010, -1, 0, 0), "valid 2/28/2010 -1:00:00");
// Leap year.
t.ok (ISO8601d::leapYear (2008), "2008 is a leap year");
t.notok (ISO8601d::leapYear (2007), "2007 is not a leap year");
t.ok (ISO8601d::leapYear (2000), "2000 is a leap year");
t.notok (ISO8601d::leapYear (1900), "1900 is not a leap year");
// Days in year.
t.is (ISO8601d::daysInYear (2016), 366, "366 days in 2016");
t.is (ISO8601d::daysInYear (2015), 365, "365 days in 2015");
// Days in month.
t.is (ISO8601d::daysInMonth (2, 2008), 29, "29 days in February 2008");
t.is (ISO8601d::daysInMonth (2, 2007), 28, "28 days in February 2007");
// Names.
t.is (ISO8601d::monthName (1), "January", "1 = January");
t.is (ISO8601d::monthName (2), "February", "2 = February");
t.is (ISO8601d::monthName (3), "March", "3 = March");
t.is (ISO8601d::monthName (4), "April", "4 = April");
t.is (ISO8601d::monthName (5), "May", "5 = May");
t.is (ISO8601d::monthName (6), "June", "6 = June");
t.is (ISO8601d::monthName (7), "July", "7 = July");
t.is (ISO8601d::monthName (8), "August", "8 = August");
t.is (ISO8601d::monthName (9), "September", "9 = September");
t.is (ISO8601d::monthName (10), "October", "10 = October");
t.is (ISO8601d::monthName (11), "November", "11 = November");
t.is (ISO8601d::monthName (12), "December", "12 = December");
// Names.
t.is (ISO8601d::monthOfYear ("January"), 1, "January = 1");
t.is (ISO8601d::monthOfYear ("February"), 2, "February = 2");
t.is (ISO8601d::monthOfYear ("March"), 3, "March = 3");
t.is (ISO8601d::monthOfYear ("April"), 4, "April = 4");
t.is (ISO8601d::monthOfYear ("May"), 5, "May = 5");
t.is (ISO8601d::monthOfYear ("June"), 6, "June = 6");
t.is (ISO8601d::monthOfYear ("July"), 7, "July = 7");
t.is (ISO8601d::monthOfYear ("August"), 8, "August = 8");
t.is (ISO8601d::monthOfYear ("September"), 9, "September = 9");
t.is (ISO8601d::monthOfYear ("October"), 10, "October = 10");
t.is (ISO8601d::monthOfYear ("November"), 11, "November = 11");
t.is (ISO8601d::monthOfYear ("December"), 12, "December = 12");
t.is (ISO8601d::dayName (0), "Sunday", "0 == Sunday");
t.is (ISO8601d::dayName (1), "Monday", "1 == Monday");
t.is (ISO8601d::dayName (2), "Tuesday", "2 == Tuesday");
t.is (ISO8601d::dayName (3), "Wednesday", "3 == Wednesday");
t.is (ISO8601d::dayName (4), "Thursday", "4 == Thursday");
t.is (ISO8601d::dayName (5), "Friday", "5 == Friday");
t.is (ISO8601d::dayName (6), "Saturday", "6 == Saturday");
t.is (ISO8601d::dayOfWeek ("SUNDAY"), 0, "SUNDAY == 0");
t.is (ISO8601d::dayOfWeek ("sunday"), 0, "sunday == 0");
t.is (ISO8601d::dayOfWeek ("Sunday"), 0, "Sunday == 0");
t.is (ISO8601d::dayOfWeek ("Monday"), 1, "Monday == 1");
t.is (ISO8601d::dayOfWeek ("Tuesday"), 2, "Tuesday == 2");
t.is (ISO8601d::dayOfWeek ("Wednesday"), 3, "Wednesday == 3");
t.is (ISO8601d::dayOfWeek ("Thursday"), 4, "Thursday == 4");
t.is (ISO8601d::dayOfWeek ("Friday"), 5, "Friday == 5");
t.is (ISO8601d::dayOfWeek ("Saturday"), 6, "Saturday == 6");
ISO8601d happyNewYear (1, 1, 2008);
t.is (happyNewYear.dayOfWeek (), 2, "1/1/2008 == Tuesday");
t.is (happyNewYear.month (), 1, "1/1/2008 == January");
t.is (happyNewYear.day (), 1, "1/1/2008 == 1");
t.is (happyNewYear.year (), 2008, "1/1/2008 == 2008");
t.is (happyNewYear.toString (), "1/1/2008", "toString 1/1/2008");
int m, d, y;
happyNewYear.toMDY (m, d, y);
t.is (m, 1, "1/1/2008 == January");
t.is (d, 1, "1/1/2008 == 1");
t.is (y, 2008, "1/1/2008 == 2008");
ISO8601d epoch (9, 8, 2001);
t.ok ((int)epoch.toEpoch () < 1000000000, "9/8/2001 < 1,000,000,000");
epoch += 172800;
t.ok ((int)epoch.toEpoch () > 1000000000, "9/10/2001 > 1,000,000,000");
ISO8601d fromEpoch (epoch.toEpoch ());
t.is (fromEpoch.toString (), epoch.toString (), "ctor (time_t)");
ISO8601d iso (1000000000);
t.is (iso.toISO (), "20010909T014640Z", "1,000,000,000 -> 20010909T014640Z");
// Quantization.
ISO8601d quant (1234526400);
t.is (quant.startOfDay ().toString ("YMDHNS"), "20090213000000", "1234526400 -> 2/13/2009 12:00:00 UTC -> 2/13/2009 0:00:00");
t.is (quant.startOfWeek ().toString ("YMDHNS"), "20090208000000", "1234526400 -> 2/13/2009 12:00:00 UTC -> 2/8/2009 0:00:00");
t.is (quant.startOfMonth ().toString ("YMDHNS"), "20090201000000", "1234526400 -> 2/13/2009 12:00:00 UTC -> 2/1/2009 0:00:00");
t.is (quant.startOfYear ().toString ("YMDHNS"), "20090101000000", "1234526400 -> 2/13/2009 12:00:00 UTC -> 1/1/2009 0:00:00");
// Date parsing.
ISO8601d fromString1 ("1/1/2008", "m/d/Y");
t.is (fromString1.month (), 1, "ctor (std::string) -> m");
t.is (fromString1.day (), 1, "ctor (std::string) -> d");
t.is (fromString1.year (), 2008, "ctor (std::string) -> y");
ISO8601d fromString2 ("20080101", "YMD");
t.is (fromString2.month (), 1, "ctor (std::string) -> m");
t.is (fromString2.day (), 1, "ctor (std::string) -> d");
t.is (fromString2.year (), 2008, "ctor (std::string) -> y");
ISO8601d fromString3 ("12/31/2007", "m/d/Y");
t.is (fromString3.month (), 12, "ctor (std::string) -> m");
t.is (fromString3.day (), 31, "ctor (std::string) -> d");
t.is (fromString3.year (), 2007, "ctor (std::string) -> y");
/*
ISO8601d fromString4 ("01/01/2008", "m/d/Y");
t.is (fromString4.month (), 1, "ctor (std::string) -> m");
t.is (fromString4.day (), 1, "ctor (std::string) -> d");
t.is (fromString4.year (), 2008, "ctor (std::string) -> y");
ISO8601d fromString5 ("Tue 05 Feb 2008 (06)", "a D b Y (V)");
t.is (fromString5.month (), 2, "ctor (std::string) -> m");
t.is (fromString5.day (), 5, "ctor (std::string) -> d");
t.is (fromString5.year (), 2008, "ctor (std::string) -> y");
ISO8601d fromString6 ("Tuesday, February 5, 2008", "A, B d, Y");
t.is (fromString6.month (), 2, "ctor (std::string) -> m");
t.is (fromString6.day (), 5, "ctor (std::string) -> d");
t.is (fromString6.year (), 2008, "ctor (std::string) -> y");
ISO8601d fromString7 ("w01 Tue 2008-01-01", "wV a Y-M-D");
t.is (fromString7.month (), 1, "ctor (std::string) -> m");
t.is (fromString7.day (), 1, "ctor (std::string) -> d");
t.is (fromString7.year (), 2008, "ctor (std::string) -> y");
ISO8601d fromString8 ("6/7/2010 1:23:45", "m/d/Y h:N:S");
t.is (fromString8.month (), 6, "ctor (std::string) -> m");
t.is (fromString8.day (), 7, "ctor (std::string) -> d");
t.is (fromString8.year (), 2010, "ctor (std::string) -> Y");
t.is (fromString8.hour (), 1, "ctor (std::string) -> h");
t.is (fromString8.minute (), 23, "ctor (std::string) -> N");
t.is (fromString8.second (), 45, "ctor (std::string) -> S");
ISO8601d fromString9 ("6/7/2010 01:23:45", "m/d/Y H:N:S");
t.is (fromString9.month (), 6, "ctor (std::string) -> m");
t.is (fromString9.day (), 7, "ctor (std::string) -> d");
t.is (fromString9.year (), 2010, "ctor (std::string) -> Y");
t.is (fromString9.hour (), 1, "ctor (std::string) -> h");
t.is (fromString9.minute (), 23, "ctor (std::string) -> N");
t.is (fromString9.second (), 45, "ctor (std::string) -> S");
ISO8601d fromString10 ("6/7/2010 12:34:56", "m/d/Y H:N:S");
t.is (fromString10.month (), 6, "ctor (std::string) -> m");
t.is (fromString10.day (), 7, "ctor (std::string) -> d");
t.is (fromString10.year (), 2010, "ctor (std::string) -> Y");
t.is (fromString10.hour (), 12, "ctor (std::string) -> h");
t.is (fromString10.minute (), 34, "ctor (std::string) -> N");
t.is (fromString1.second (), 56, "ctor (std::string) -> S");
*/
// Day of year
t.is (ISO8601d ("1/1/2011", "m/d/Y").dayOfYear (), 1, "dayOfYear (1/1/2011) -> 1");
t.is (ISO8601d ("5/1/2011", "m/d/Y").dayOfYear (), 121, "dayOfYear (5/1/2011) -> 121");
t.is (ISO8601d ("12/31/2011", "m/d/Y").dayOfYear (), 365, "dayOfYear (12/31/2011) -> 365");
/*
// Relative dates.
Date r1 ("today");
t.ok (r1.sameDay (now), "today = now");
Date r4 ("sunday");
if (now.dayOfWeek () >= 0)
t.ok (r4.sameDay (now + (0 - now.dayOfWeek () + 7) * 86400), "next sunday");
else
t.ok (r4.sameDay (now + (0 - now.dayOfWeek ()) * 86400), "next sunday");;
Date r5 ("monday");
if (now.dayOfWeek () >= 1)
t.ok (r5.sameDay (now + (1 - now.dayOfWeek () + 7) * 86400), "next monday");
else
t.ok (r5.sameDay (now + (1 - now.dayOfWeek ()) * 86400), "next monday");;
Date r6 ("tuesday");
if (now.dayOfWeek () >= 2)
t.ok (r6.sameDay (now + (2 - now.dayOfWeek () + 7) * 86400), "next tuesday");
else
t.ok (r6.sameDay (now + (2 - now.dayOfWeek ()) * 86400), "next tuesday");;
Date r7 ("wednesday");
if (now.dayOfWeek () >= 3)
t.ok (r7.sameDay (now + (3 - now.dayOfWeek () + 7) * 86400), "next wednesday");
else
t.ok (r7.sameDay (now + (3 - now.dayOfWeek ()) * 86400), "next wednesday");;
Date r8 ("thursday");
if (now.dayOfWeek () >= 4)
t.ok (r8.sameDay (now + (4 - now.dayOfWeek () + 7) * 86400), "next thursday");
else
t.ok (r8.sameDay (now + (4 - now.dayOfWeek ()) * 86400), "next thursday");;
Date r9 ("friday");
if (now.dayOfWeek () >= 5)
t.ok (r9.sameDay (now + (5 - now.dayOfWeek () + 7) * 86400), "next friday");
else
t.ok (r9.sameDay (now + (5 - now.dayOfWeek ()) * 86400), "next friday");;
Date r10 ("saturday");
if (now.dayOfWeek () >= 6)
t.ok (r10.sameDay (now + (6 - now.dayOfWeek () + 7) * 86400), "next saturday");
else
t.ok (r10.sameDay (now + (6 - now.dayOfWeek ()) * 86400), "next saturday");;
Date r11 ("eow");
t.ok (r11 < now + (8 * 86400), "eow < 7 days away");
Date r12 ("eocw");
t.ok (r12 > now - (8 * 86400), "eocw < 7 days in the past");
Date r13 ("eom");
t.ok (r13.sameMonth (now), "eom in same month as now");
Date r14 ("eocm");
t.ok (r14.sameMonth (now), "eocm in same month as now");
Date r15 ("eoy");
t.ok (r15.sameYear (now), "eoy in same year as now");
Date r16 ("sow");
t.ok (r16 < now + (8 * 86400), "sow < 7 days away");
Date r23 ("socw");
t.ok (r23 > now - (8 * 86400), "sow < 7 days in the past");
Date r17 ("som");
t.notok (r17.sameMonth (now), "som not in same month as now");
Date r18 ("socm");
t.ok (r18.sameMonth (now), "socm in same month as now");
Date r19 ("soy");
t.notok (r19.sameYear (now), "soy not in same year as now");
Date first ("1st");
t.notok (first.sameMonth (now), "1st not in same month as now");
t.is (first.day (), 1, "1st day is 1");
Date later ("later");
t.is (later.month (), 1, "later -> m = 1");
t.is (later.day (), 18, "later -> d = 18");
t.is (later.year (), 2038, "later -> y = 2038");
// Quarters
Date soq ("soq");
Date eoq ("eoq");
t.is (soq.day (), 1, "soq is the first day of a month");
t.is (eoq.day () / 10, 3, "eoq is the 30th or 31th of a month");
t.is (soq.month () % 3, 1, "soq month is 1, 4, 7 or 10");
t.is (eoq.month () % 3, 0, "eoq month is 3, 6, 9 or 12");
// Note: these fail during the night of daylight savings end.
t.ok (soq.sameYear (now) ||
(now.month () >= 10 &&
soq.year () == now.year () + 1), "soq is in same year as now");
t.ok (eoq.sameYear (now), "eoq is in same year as now");
// ISO8601d::sameHour
ISO8601d r20 ("6/7/2010 01:00:00", "m/d/Y H:N:S");
ISO8601d r21 ("6/7/2010 01:59:59", "m/d/Y H:N:S");
t.ok (r20.sameHour (r21), "two dates within the same hour");
ISO8601d r22 ("6/7/2010 00:59:59", "m/d/Y H:N:S");
t.notok (r20.sameHour (r22), "two dates not within the same hour");
*/
// ISO8601d::operator-
ISO8601d r25 (1234567890);
t.is ((r25 - 1).toEpoch (), 1234567889, "1234567890 - 1 = 1234567889");
// ISO8601d::operator--
ISO8601d r26 (11, 7, 2010, 23, 59, 59);
r26--;
t.is (r26.toString ("YMDHNS"), "20101106235959", "decrement across fall DST boundary");
ISO8601d r27 (3, 14, 2010, 23, 59, 59);
r27--;
t.is (r27.toString ("YMDHNS"), "20100313235959", "decrement across spring DST boundary");
// ISO8601d::operator++
ISO8601d r28 (11, 6, 2010, 23, 59, 59);
r28++;
t.is (r28.toString ("YMDHNS"), "20101107235959", "increment across fall DST boundary");
ISO8601d r29 (3, 13, 2010, 23, 59, 59);
r29++;
t.is (r29.toString ("YMDHNS"), "20100314235959", "increment across spring DST boundary");
// int ISO8601d::length (const std::string&);
t.is (ISO8601d::length ("m"), 2, "length 'm' --> 2");
t.is (ISO8601d::length ("M"), 2, "length 'M' --> 2");
t.is (ISO8601d::length ("d"), 2, "length 'd' --> 2");
t.is (ISO8601d::length ("D"), 2, "length 'D' --> 2");
t.is (ISO8601d::length ("y"), 2, "length 'y' --> 2");
t.is (ISO8601d::length ("Y"), 4, "length 'Y' --> 4");
t.is (ISO8601d::length ("a"), 3, "length 'a' --> 3");
t.is (ISO8601d::length ("A"), 10, "length 'A' --> 10");
t.is (ISO8601d::length ("b"), 3, "length 'b' --> 3");
t.is (ISO8601d::length ("B"), 10, "length 'B' --> 10");
t.is (ISO8601d::length ("v"), 2, "length 'v' --> 2");
t.is (ISO8601d::length ("V"), 2, "length 'V' --> 2");
t.is (ISO8601d::length ("h"), 2, "length 'h' --> 2");
t.is (ISO8601d::length ("H"), 2, "length 'H' --> 2");
t.is (ISO8601d::length ("n"), 2, "length 'n' --> 2");
t.is (ISO8601d::length ("N"), 2, "length 'N' --> 2");
t.is (ISO8601d::length ("s"), 2, "length 's' --> 2");
t.is (ISO8601d::length ("S"), 2, "length 'S' --> 2");
t.is (ISO8601d::length ("j"), 3, "length 'j' --> 3");
t.is (ISO8601d::length ("J"), 3, "length 'J' --> 3");
t.is (ISO8601d::length (" "), 1, "length ' ' --> 1");
// Depletion requirement.
ISO8601d r30 ("Mon Jun 30 2014", "a b D Y");
t.is (r30.toString ("YMDHNS"), "20140630000000", "Depletion required on complex format with spaces");
/*
std::string::size_type i = 0;
ISO8601d r31 ("Mon Jun 30 2014 xxx", i, "a b D Y");
t.is (r31.toString ("YMDHNS"), "20140630000000", "Depletion not required on complex format with spaces");
t.is ((int)i, 15, "Depletion not required on complex format with spaces, 15 chars");
*/
}
catch (const std::string& e)
{
t.fail ("Exception thrown.");
t.diag (e);
}
return 0; return 0;
} }

View file

@ -44,7 +44,7 @@ void testParse (
int in_hours, int in_hours,
int in_minutes, int in_minutes,
int in_seconds, int in_seconds,
time_t in_value, time_t in_period,
const std::string& output, const std::string& output,
const std::string& vague) const std::string& vague)
{ {
@ -61,7 +61,7 @@ void testParse (
t.is (iso._hours, in_hours, label + "_hours"); t.is (iso._hours, in_hours, label + "_hours");
t.is (iso._minutes, in_minutes, label + "_minutes"); t.is (iso._minutes, in_minutes, label + "_minutes");
t.is (iso._seconds, in_seconds, label + "_seconds"); t.is (iso._seconds, in_seconds, label + "_seconds");
t.is ((size_t) iso._value, (size_t) in_value, label + "_value"); t.is ((size_t) iso._period, (size_t) in_period, label + "_period");
t.is (iso.format (), output, label + " format"); t.is (iso.format (), output, label + " format");
t.is (iso.formatVague (), vague, label + " formatVague"); t.is (iso.formatVague (), vague, label + " formatVague");
} }

View file

@ -335,8 +335,6 @@ int main (int argc, char** argv)
{ "/long/path/to/file.txt", { { "/long/path/to/file.txt", Lexer::Type::path }, NO, NO, NO, NO }, }, { "/long/path/to/file.txt", { { "/long/path/to/file.txt", Lexer::Type::path }, NO, NO, NO, NO }, },
// Word // Word
{ "9th", { { "9th", Lexer::Type::word }, NO, NO, NO, NO }, },
{ "10th", { { "10th", Lexer::Type::word }, NO, NO, NO, NO }, },
{ "1.foo.bar", { { "1.foo.bar", Lexer::Type::word }, NO, NO, NO, NO }, }, { "1.foo.bar", { { "1.foo.bar", Lexer::Type::word }, NO, NO, NO, NO }, },
// Identifier // Identifier
@ -348,9 +346,6 @@ int main (int argc, char** argv)
{ "foo.bar", { { "foo.bar", Lexer::Type::identifier }, NO, NO, NO, NO }, }, { "foo.bar", { { "foo.bar", Lexer::Type::identifier }, NO, NO, NO, NO }, },
{ "a1a1a1a1_a1a1_a1a1_a1a1_a1a1a1a1a1a1", { { "a1a1a1a1_a1a1_a1a1_a1a1_a1a1a1a1a1a1", Lexer::Type::identifier }, NO, NO, NO, NO }, }, { "a1a1a1a1_a1a1_a1a1_a1a1_a1a1a1a1a1a1", { { "a1a1a1a1_a1a1_a1a1_a1a1_a1a1a1a1a1a1", Lexer::Type::identifier }, NO, NO, NO, NO }, },
// Not a date, because Eval extracts named dates via data source, and Date/ISO8601d does not do that.
{ "today", { { "today", Lexer::Type::identifier }, NO, NO, NO, NO }, },
// Word that starts wih 'or', which is an operator, but should be ignored. // Word that starts wih 'or', which is an operator, but should be ignored.
{ "ordinary", { { "ordinary", Lexer::Type::identifier }, NO, NO, NO, NO }, }, { "ordinary", { { "ordinary", Lexer::Type::identifier }, NO, NO, NO, NO }, },
@ -458,6 +453,9 @@ int main (int argc, char** argv)
{ "2015-02-17", { { "2015-02-17", Lexer::Type::date }, NO, NO, NO, NO }, }, { "2015-02-17", { { "2015-02-17", Lexer::Type::date }, NO, NO, NO, NO }, },
{ "2013-11-29T22:58:00Z", { { "2013-11-29T22:58:00Z", Lexer::Type::date }, NO, NO, NO, NO }, }, { "2013-11-29T22:58:00Z", { { "2013-11-29T22:58:00Z", Lexer::Type::date }, NO, NO, NO, NO }, },
{ "20131129T225800Z", { { "20131129T225800Z", Lexer::Type::date }, NO, NO, NO, NO }, }, { "20131129T225800Z", { { "20131129T225800Z", Lexer::Type::date }, NO, NO, NO, NO }, },
{ "9th", { { "9th", Lexer::Type::date }, NO, NO, NO, NO }, },
{ "10th", { { "10th", Lexer::Type::date }, NO, NO, NO, NO }, },
{ "today", { { "today", Lexer::Type::date }, NO, NO, NO, NO }, },
// Duration // Duration
{ "year", { { "year", Lexer::Type::duration }, NO, NO, NO, NO }, }, { "year", { { "year", Lexer::Type::duration }, NO, NO, NO, NO }, },

View file

@ -29,7 +29,7 @@
#include <Context.h> #include <Context.h>
#include <Nibbler.h> #include <Nibbler.h>
#ifdef NIBBLER_FEATURE_DATE #ifdef NIBBLER_FEATURE_DATE
#include <Date.h> #include <ISO8601.h>
#endif #endif
#include <test.h> #include <test.h>
@ -65,7 +65,7 @@ int main (int argc, char** argv)
time_t ti; time_t ti;
#ifdef NIBBLER_FEATURE_DATE #ifdef NIBBLER_FEATURE_DATE
Date dt; ISO8601d dt;
#endif #endif
std::vector <std::string> options; std::vector <std::string> options;
@ -533,56 +533,56 @@ int main (int argc, char** argv)
t.diag ("Nibbler::getDate"); t.diag ("Nibbler::getDate");
n = Nibbler ("1/1/2008"); n = Nibbler ("1/1/2008");
t.ok (n.getDate ("m/d/Y", ti), "m/d/Y ok"); t.ok (n.getDate ("m/d/Y", ti), "m/d/Y ok");
dt = Date (ti); dt = ISO8601d (ti);
t.is (dt.month (), 1, "ctor (std::string) -> m"); t.is (dt.month (), 1, "ctor (std::string) -> m");
t.is (dt.day (), 1, "ctor (std::string) -> d"); t.is (dt.day (), 1, "ctor (std::string) -> d");
t.is (dt.year (), 2008, "ctor (std::string) -> y"); t.is (dt.year (), 2008, "ctor (std::string) -> y");
n = Nibbler ("20080101"); n = Nibbler ("20080101");
t.ok (n.getDate ("YMD", ti), "YMD ok"); t.ok (n.getDate ("YMD", ti), "YMD ok");
dt = Date (ti); dt = ISO8601d (ti);
t.is (dt.month (), 1, "ctor (std::string) -> m"); t.is (dt.month (), 1, "ctor (std::string) -> m");
t.is (dt.day (), 1, "ctor (std::string) -> d"); t.is (dt.day (), 1, "ctor (std::string) -> d");
t.is (dt.year (), 2008, "ctor (std::string) -> y"); t.is (dt.year (), 2008, "ctor (std::string) -> y");
n = Nibbler ("12/31/2007"); n = Nibbler ("12/31/2007");
t.ok (n.getDate ("m/d/Y", ti), "m/d/Y ok"); t.ok (n.getDate ("m/d/Y", ti), "m/d/Y ok");
dt = Date (ti); dt = ISO8601d (ti);
t.is (dt.month (), 12, "ctor (std::string) -> m"); t.is (dt.month (), 12, "ctor (std::string) -> m");
t.is (dt.day (), 31, "ctor (std::string) -> d"); t.is (dt.day (), 31, "ctor (std::string) -> d");
t.is (dt.year (), 2007, "ctor (std::string) -> y"); t.is (dt.year (), 2007, "ctor (std::string) -> y");
n = Nibbler ("20071231"); n = Nibbler ("20071231");
t.ok (n.getDate ("YMD", ti), "YMD ok"); t.ok (n.getDate ("YMD", ti), "YMD ok");
dt = Date (ti); dt = ISO8601d (ti);
t.is (dt.month (), 12, "ctor (std::string) -> m"); t.is (dt.month (), 12, "ctor (std::string) -> m");
t.is (dt.day (), 31, "ctor (std::string) -> d"); t.is (dt.day (), 31, "ctor (std::string) -> d");
t.is (dt.year (), 2007, "ctor (std::string) -> y"); t.is (dt.year (), 2007, "ctor (std::string) -> y");
n = Nibbler ("Tue 01 Jan 2008 (01)"); n = Nibbler ("Tue 01 Jan 2008 (01)");
t.ok (n.getDate ("a D b Y (V)", ti), "a D b Y (V)"); t.ok (n.getDate ("a D b Y (V)", ti), "a D b Y (V)");
dt = Date (ti); dt = ISO8601d (ti);
t.is (dt.month (), 1, "ctor (std::string) -> m"); t.is (dt.month (), 1, "ctor (std::string) -> m");
t.is (dt.day (), 1, "ctor (std::string) -> d"); t.is (dt.day (), 1, "ctor (std::string) -> d");
t.is (dt.year (), 2008, "ctor (std::string) -> y"); t.is (dt.year (), 2008, "ctor (std::string) -> y");
n = Nibbler ("Tuesday, January 1, 2008"); n = Nibbler ("Tuesday, January 1, 2008");
t.ok (n.getDate ("A, B d, Y", ti), "A, B d, Y ok"); t.ok (n.getDate ("A, B d, Y", ti), "A, B d, Y ok");
dt = Date (ti); dt = ISO8601d (ti);
t.is (dt.month (), 1, "ctor (std::string) -> m"); t.is (dt.month (), 1, "ctor (std::string) -> m");
t.is (dt.day (), 1, "ctor (std::string) -> d"); t.is (dt.day (), 1, "ctor (std::string) -> d");
t.is (dt.year (), 2008, "ctor (std::string) -> y"); t.is (dt.year (), 2008, "ctor (std::string) -> y");
n = Nibbler ("w01 Tue 2008-01-01"); n = Nibbler ("w01 Tue 2008-01-01");
t.ok (n.getDate ("wV a Y-M-D", ti), "wV a Y-M-D ok"); t.ok (n.getDate ("wV a Y-M-D", ti), "wV a Y-M-D ok");
dt = Date (ti); dt = ISO8601d (ti);
t.is (dt.month (), 1, "ctor (std::string) -> m"); t.is (dt.month (), 1, "ctor (std::string) -> m");
t.is (dt.day (), 1, "ctor (std::string) -> d"); t.is (dt.day (), 1, "ctor (std::string) -> d");
t.is (dt.year (), 2008, "ctor (std::string) -> y"); t.is (dt.year (), 2008, "ctor (std::string) -> y");
n = Nibbler ("6/7/2010 1:23:45"); n = Nibbler ("6/7/2010 1:23:45");
t.ok (n.getDate ("m/d/Y h:N:S", ti), "m/d/Y h:N:S ok"); t.ok (n.getDate ("m/d/Y h:N:S", ti), "m/d/Y h:N:S ok");
dt = Date (ti); dt = ISO8601d (ti);
t.is (dt.month (), 6, "ctor (std::string) -> m"); t.is (dt.month (), 6, "ctor (std::string) -> m");
t.is (dt.day (), 7, "ctor (std::string) -> d"); t.is (dt.day (), 7, "ctor (std::string) -> d");
t.is (dt.year (), 2010, "ctor (std::string) -> Y"); t.is (dt.year (), 2010, "ctor (std::string) -> Y");
@ -592,7 +592,7 @@ int main (int argc, char** argv)
n = Nibbler ("6/7/2010 01:23:45"); n = Nibbler ("6/7/2010 01:23:45");
t.ok (n.getDate ("m/d/Y H:N:S", ti), "m/d/Y H:N:S ok"); t.ok (n.getDate ("m/d/Y H:N:S", ti), "m/d/Y H:N:S ok");
dt = Date (ti); dt = ISO8601d (ti);
t.is (dt.month (), 6, "ctor (std::string) -> m"); t.is (dt.month (), 6, "ctor (std::string) -> m");
t.is (dt.day (), 7, "ctor (std::string) -> d"); t.is (dt.day (), 7, "ctor (std::string) -> d");
t.is (dt.year (), 2010, "ctor (std::string) -> Y"); t.is (dt.year (), 2010, "ctor (std::string) -> Y");
@ -602,7 +602,7 @@ int main (int argc, char** argv)
n = Nibbler ("6/7/2010 12:34:56"); n = Nibbler ("6/7/2010 12:34:56");
t.ok (n.getDate ("m/d/Y H:N:S", ti), "m/d/Y H:N:S ok"); t.ok (n.getDate ("m/d/Y H:N:S", ti), "m/d/Y H:N:S ok");
dt = Date (ti); dt = ISO8601d (ti);
t.is (dt.month (), 6, "ctor (std::string) -> m"); t.is (dt.month (), 6, "ctor (std::string) -> m");
t.is (dt.day (), 7, "ctor (std::string) -> d"); t.is (dt.day (), 7, "ctor (std::string) -> d");
t.is (dt.year (), 2010, "ctor (std::string) -> Y"); t.is (dt.year (), 2010, "ctor (std::string) -> Y");
@ -612,7 +612,7 @@ int main (int argc, char** argv)
n = Nibbler ("2010"); n = Nibbler ("2010");
t.ok (n.getDate ("Y", ti), "Y ok"); t.ok (n.getDate ("Y", ti), "Y ok");
dt = Date (ti); dt = ISO8601d (ti);
t.is (dt.month (), 1, "ctor (std::string) -> m"); t.is (dt.month (), 1, "ctor (std::string) -> m");
t.is (dt.day (), 1, "ctor (std::string) -> d"); t.is (dt.day (), 1, "ctor (std::string) -> d");
t.is (dt.year (), 2010, "ctor (std::string) -> Y"); t.is (dt.year (), 2010, "ctor (std::string) -> Y");
@ -622,8 +622,8 @@ int main (int argc, char** argv)
n = Nibbler ("17:18:19"); n = Nibbler ("17:18:19");
t.ok (n.getDate ("H:N:S", ti), "H:N:S ok"); t.ok (n.getDate ("H:N:S", ti), "H:N:S ok");
dt = Date (ti); dt = ISO8601d (ti);
Date now = Date (); ISO8601d now;
t.is (dt.month (), now.month(), "ctor (std::string) -> m"); t.is (dt.month (), now.month(), "ctor (std::string) -> m");
t.is (dt.day (), now.day(), "ctor (std::string) -> d"); t.is (dt.day (), now.day(), "ctor (std::string) -> d");
t.is (dt.year (), now.year(), "ctor (std::string) -> Y"); t.is (dt.year (), now.year(), "ctor (std::string) -> Y");

View file

@ -54,7 +54,7 @@ class TestTimesheet(TestCase):
# C0 completed, this week # C0 completed, this week
# C1 completed, last week # C1 completed, last week
# C2 completed, 2wks ago # C2 completed, 2wks ago
now = time() now = int(time())
seven = now - 7 * 86400 seven = now - 7 * 86400
fourteen = now - 14 * 86400 fourteen = now - 14 * 86400