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
Context.cpp Context.h
DOM.cpp DOM.h
Date.cpp Date.h
Dates.cpp Dates.h
Eval.cpp Eval.h
Filter.cpp Filter.h

View file

@ -33,7 +33,7 @@
#include <inttypes.h>
#include <unistd.h>
#include <stdlib.h>
#include <Date.h>
#include <ISO8601.h>
#include <FS.h>
#include <Timer.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");
// loc+0^ +14^ +21^
Date now;
ISO8601d now;
std::stringstream contents;
contents << "# [Created by "
<< PACKAGE_STRING

View file

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

View file

@ -32,7 +32,6 @@
#include <Context.h>
#include <Nibbler.h>
#include <ISO8601.h>
#include <Date.h>
#include <text.h>
#include <i18n.h>
#include <DOM.h>
@ -300,7 +299,7 @@ bool DOM::get (const std::string& name, const Task& task, Variant& value)
ISO8601p iso;
std::string::size_type cursor = 0;
if (iso.parse (period, cursor))
value = Variant ((time_t) iso._value, Variant::type_duration);
value = Variant ((time_t) iso, Variant::type_duration);
else
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")
{
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; }
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; }
@ -384,7 +383,7 @@ bool DOM::get (const std::string& name, const Task& task, Variant& value)
// <annotations>.<N>.entry.hour
// <annotations>.<N>.entry.minute
// <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; }
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; }

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 <text.h>
#include <Dates.h>
#include <Date.h>
#include <ISO8601.h>
#include <Lexer.h>
#include <CLI2.h>
#include <i18n.h>
@ -38,14 +38,14 @@
////////////////////////////////////////////////////////////////////////////////
static bool isMonth (const std::string& name, int& i)
{
i = Date::monthOfYear (name) - 1;
i = ISO8601d::monthOfYear (name) - 1;
return i != -2 ? true : false;
}
////////////////////////////////////////////////////////////////////////////////
static bool isDay (const std::string& name, int& i)
{
i = Date::dayOfWeek (name);
i = ISO8601d::dayOfWeek (name);
return i != -1 ? true : false;
}
@ -103,6 +103,7 @@ static void midsommarafton (struct tm* t)
}
////////////////////////////////////////////////////////////////////////////////
// Note how these are all single words:
// <day>
// <month>
// Nth
@ -302,7 +303,7 @@ bool namedDates (const std::string& name, Variant& value)
t->tm_hour = 24;
t->tm_min = 0;
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;
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 (d < number &&
number <= Date::daysInMonth (m, y))
number <= ISO8601d::daysInMonth (m, y))
{
t->tm_hour = t->tm_min = t->tm_sec = 0;
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
//
////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_ISO8601
#define INCLUDED_ISO8601
@ -33,15 +34,84 @@
class ISO8601d
{
public:
static std::string weekstart;
static int minimumMatchLength;
static bool isoEnabled;
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 (const ISO8601d&); // Unimplemented
ISO8601d& operator= (const ISO8601d&); // Unimplemented
operator time_t () const;
bool parse (const std::string&, std::string::size_type&);
void clear ();
bool parse (const std::string&, std::string::size_type&, const std::string& format = "");
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:
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_ext (Nibbler&);
bool parse_date_ext (Nibbler&);
@ -49,7 +119,6 @@ private:
bool parse_time_ext (Nibbler&);
bool parse_time_utc_ext (Nibbler&);
bool parse_time_off_ext (Nibbler&);
int dayOfWeek (int, int, int);
bool validate ();
void resolve ();
@ -63,13 +132,15 @@ public:
int _seconds;
int _offset;
bool _utc;
time_t _value;
time_t _date;
};
// Period
class ISO8601p
{
public:
static bool isoEnabled;
ISO8601p ();
ISO8601p (time_t);
ISO8601p (const std::string&);
@ -81,11 +152,11 @@ public:
operator std::string () const;
operator time_t () const;
bool parse (const std::string&, std::string::size_type&);
void clear ();
const std::string format () const;
const std::string formatVague () const;
private:
void clear ();
bool parse_designated (Nibbler&);
bool validate ();
void resolve ();
@ -97,11 +168,9 @@ public:
int _hours;
int _minutes;
int _seconds;
time_t _value;
time_t _period;
};
// TODO Recurrence
#endif
////////////////////////////////////////////////////////////////////////////////

View file

@ -28,14 +28,12 @@
#include <ctype.h>
#include <Lexer.h>
#include <ISO8601.h>
#include <Date.h>
#include <utf8.h>
static const std::string uuid_pattern = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
static const unsigned int uuid_min_length = 8;
std::string Lexer::dateFormat = "";
bool Lexer::isoEnabled = true;
std::string::size_type Lexer::minimumMatchLength = 3;
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
// <ISO8601d> | <Date>
// <ISO8601d>
bool Lexer::isDate (std::string& token, Lexer::Type& type)
{
// Try an ISO date parse.
if (Lexer::isoEnabled)
{
std::size_t iso_i = 0;
ISO8601d iso;
if (iso.parse (_text.substr (_cursor), iso_i))
if (iso.parse (_text.substr (_cursor), iso_i, Lexer::dateFormat))
{
type = Lexer::Type::date;
token = _text.substr (_cursor, iso_i);
_cursor += iso_i;
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;
}

View file

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

View file

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

View file

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

View file

@ -34,7 +34,7 @@
#include <signal.h>
#include <Context.h>
#include <Color.h>
#include <Date.h>
#include <ISO8601.h>
#include <i18n.h>
#include <text.h>
#include <util.h>
@ -638,7 +638,7 @@ void TDB2::update (
// old <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 ("new " + task.composeF4 () + "\n");
undo.add_line ("---\n");
@ -657,7 +657,7 @@ void TDB2::update (
// time <time>
// 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 ("---\n");
}
@ -962,7 +962,7 @@ void TDB2::show_diff (
const std::string& prior,
const std::string& when)
{
Date lastChange (strtol (when.c_str (), NULL, 10));
ISO8601d lastChange (strtol (when.c_str (), NULL, 10));
// Set the colors.
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
// completed, or need to be 'woken'.
Date now;
ISO8601d now;
std::string status;
for (auto& task : pending_tasks)
{
@ -1221,7 +1221,7 @@ int TDB2::gc ()
}
else if (status == "waiting")
{
Date wait (task.get_date ("wait"));
ISO8601d wait (task.get_date ("wait"));
if (wait < now)
{
task.set ("status", "pending");
@ -1261,7 +1261,7 @@ int TDB2::gc ()
}
else if (status == "waiting")
{
Date wait (task.get_date ("wait"));
ISO8601d wait (task.get_date ("wait"));
if (wait < now)
{
task.set ("status", "pending");

View file

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

View file

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

View file

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

View file

@ -27,7 +27,7 @@
#include <cmake.h>
#include <stdlib.h>
#include <Context.h>
#include <Date.h>
#include <ISO8601.h>
#include <ColDescription.h>
#include <text.h>
#include <utf8.h>
@ -55,7 +55,7 @@ ColumnDescription::ColumnDescription ()
if (_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 a1 = STRING_COLUMN_EXAMPLES_ANNO1;
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)
{
unsigned int min_anno = _indent + Date::length (_dateformat);
unsigned int min_anno = _indent + ISO8601d::length (_dateformat);
if (min_anno > minimum)
minimum = min_anno;
@ -132,7 +132,7 @@ void ColumnDescription::measure (Task& task, unsigned int& minimum, unsigned int
if (task.annotation_count)
{
auto min_anno = Date::length (_dateformat);
auto min_anno = ISO8601d::length (_dateformat);
std::map <std::string, std::string> annos;
task.getAnnotations (annos);
for (auto& i : annos)
@ -187,7 +187,7 @@ void ColumnDescription::render (
{
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;
}
}
@ -218,7 +218,7 @@ void ColumnDescription::render (
{
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;
}
}

View file

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

View file

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

View file

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

View file

@ -32,7 +32,6 @@
#include <math.h>
#include <Context.h>
#include <Filter.h>
#include <Date.h>
#include <ISO8601.h>
#include <main.h>
#include <i18n.h>
@ -152,10 +151,10 @@ public:
private:
void generateBars ();
void optimizeGrid ();
Date quantize (const Date&);
ISO8601d quantize (const ISO8601d&);
Date increment (const Date&);
Date decrement (const Date&);
ISO8601d increment (const ISO8601d&);
ISO8601d decrement (const ISO8601d&);
void maxima ();
void yLabels (std::vector <int>&);
void calculateRates (std::vector <time_t>&);
@ -173,7 +172,7 @@ public:
int _estimated_bars; // Estimated bar count
int _actual_bars; // Calculated bar count
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
char _period; // D, W, M
std::string _title; // Additional description
@ -226,13 +225,13 @@ void Chart::scan (std::vector <Task>& tasks)
generateBars ();
// Not quantized, so that "while (xxx < now)" is inclusive.
Date now;
ISO8601d now;
time_t epoch;
for (auto& task : tasks)
{
// 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 ();
if (_bars.find (epoch) != _bars.end ())
@ -246,7 +245,7 @@ void Chart::scan (std::vector <Task>& tasks)
{
if (task.has ("start"))
{
Date start = quantize (Date (task.get_date ("start")));
ISO8601d start = quantize (ISO8601d (task.get_date ("start")));
while (from < start)
{
epoch = from.toEpoch ();
@ -280,7 +279,7 @@ void Chart::scan (std::vector <Task>& tasks)
else if (status == Task::completed)
{
// 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 ();
if (_bars.find (epoch) != _bars.end ())
@ -296,7 +295,7 @@ void Chart::scan (std::vector <Task>& tasks)
if (task.has ("start"))
{
Date start = quantize (Date (task.get_date ("start")));
ISO8601d start = quantize (ISO8601d (task.get_date ("start")));
while (from < start)
{
epoch = from.toEpoch ();
@ -323,7 +322,7 @@ void Chart::scan (std::vector <Task>& tasks)
}
else
{
Date end = quantize (Date (task.get_date ("end")));
ISO8601d end = quantize (ISO8601d (task.get_date ("end")));
while (from < end)
{
epoch = from.toEpoch ();
@ -347,7 +346,7 @@ void Chart::scan (std::vector <Task>& tasks)
else if (status == Task::deleted)
{
// Skip old deleted tasks.
Date end = quantize (Date (task.get_date ("end")));
ISO8601d end = quantize (ISO8601d (task.get_date ("end")));
epoch = end.toEpoch ();
if (_bars.find (epoch) != _bars.end ())
++_bars[epoch]._removed;
@ -357,7 +356,7 @@ void Chart::scan (std::vector <Task>& tasks)
if (task.has ("start"))
{
Date start = quantize (Date (task.get_date ("start")));
ISO8601d start = quantize (ISO8601d (task.get_date ("start")));
while (from < start)
{
epoch = from.toEpoch ();
@ -376,7 +375,7 @@ void Chart::scan (std::vector <Task>& tasks)
}
else
{
Date end = quantize (Date (task.get_date ("end")));
ISO8601d end = quantize (ISO8601d (task.get_date ("end")));
while (from < end)
{
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 == '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.
int d = input.day ();
@ -630,7 +629,7 @@ Date Chart::increment (const Date& input)
switch (_period)
{
case 'D':
if (++d > Date::daysInMonth (m, y))
if (++d > ISO8601d::daysInMonth (m, y))
{
d = 1;
@ -644,7 +643,7 @@ Date Chart::increment (const Date& input)
case 'W':
d += 7;
days = Date::daysInMonth (m, y);
days = ISO8601d::daysInMonth (m, y);
if (d > days)
{
d -= days;
@ -667,11 +666,11 @@ Date Chart::increment (const Date& input)
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.
int d = input.day ();
@ -689,7 +688,7 @@ Date Chart::decrement (const Date& input)
--y;
}
d = Date::daysInMonth (m, y);
d = ISO8601d::daysInMonth (m, y);
}
break;
@ -703,7 +702,7 @@ Date Chart::decrement (const Date& input)
y--;
}
d += Date::daysInMonth (m, y);
d += ISO8601d::daysInMonth (m, y);
}
break;
@ -717,7 +716,7 @@ Date Chart::decrement (const Date& input)
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;
// Determine the last bar date.
Date cursor;
ISO8601d cursor;
switch (_period)
{
case 'D': cursor = Date ().startOfDay (); break;
case 'W': cursor = Date ().startOfWeek (); break;
case 'M': cursor = Date ().startOfMonth (); break;
case 'D': cursor = ISO8601d ().startOfDay (); break;
case 'W': cursor = ISO8601d ().startOfWeek (); break;
case 'M': cursor = ISO8601d ().startOfMonth (); break;
}
// Iterate and determine all the other bar dates.
@ -744,7 +743,7 @@ void Chart::generateBars ()
{
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);
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 remaining_days = (int) (current_pending / (_fix_rate - _find_rate));
Date now;
ISO8601d now;
ISO8601p delta (remaining_days * 86400);
now += delta;

View file

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

View file

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

View file

@ -166,7 +166,7 @@ std::string CmdEdit::formatDate (
std::string value = task.get (attribute);
if (value.length ())
{
Date dt (value);
ISO8601d dt (value);
value = dt.toString (dateformat);
}
@ -250,12 +250,12 @@ std::string CmdEdit::formatTask (Task task, const std::string& dateformat)
task.getAnnotations (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)
<< " -- " << json::encode (anno.second) << "\n";
}
Date now;
ISO8601d now;
before << " Annotation: " << now.toString (dateformat) << " -- \n";
// Add dependencies here.
@ -379,7 +379,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string
if (formatted != value)
{
context.footnote (STRING_EDIT_ENTRY_MOD);
task.set ("entry", Date(value, dateformat).toEpochString ());
task.set ("entry", ISO8601d (value, dateformat).toEpochString ());
}
}
else
@ -396,13 +396,13 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string
if (formatted != value)
{
context.footnote (STRING_EDIT_START_MOD);
task.set ("start", Date(value, dateformat).toEpochString ());
task.set ("start", ISO8601d (value, dateformat).toEpochString ());
}
}
else
{
context.footnote (STRING_EDIT_START_MOD);
task.set ("start", Date(value, dateformat).toEpochString ());
task.set ("start", ISO8601d (value, dateformat).toEpochString ());
}
}
else
@ -425,7 +425,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string
if (formatted != value)
{
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)
@ -452,13 +452,13 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string
if (formatted != value)
{
context.footnote (STRING_EDIT_SCHED_MOD);
task.set ("scheduled", Date(value, dateformat).toEpochString ());
task.set ("scheduled", ISO8601d (value, dateformat).toEpochString ());
}
}
else
{
context.footnote (STRING_EDIT_SCHED_MOD);
task.set ("scheduled", Date(value, dateformat).toEpochString ());
task.set ("scheduled", ISO8601d (value, dateformat).toEpochString ());
}
}
else
@ -482,13 +482,13 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string
if (formatted != value)
{
context.footnote (STRING_EDIT_DUE_MOD);
task.set ("due", Date(value, dateformat).toEpochString ());
task.set ("due", ISO8601d (value, dateformat).toEpochString ());
}
}
else
{
context.footnote (STRING_EDIT_DUE_MOD);
task.set ("due", Date(value, dateformat).toEpochString ());
task.set ("due", ISO8601d (value, dateformat).toEpochString ());
}
}
else
@ -519,13 +519,13 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string
if (formatted != value)
{
context.footnote (STRING_EDIT_UNTIL_MOD);
task.set ("until", Date(value, dateformat).toEpochString ());
task.set ("until", ISO8601d (value, dateformat).toEpochString ());
}
}
else
{
context.footnote (STRING_EDIT_UNTIL_MOD);
task.set ("until", Date(value, dateformat).toEpochString ());
task.set ("until", ISO8601d (value, dateformat).toEpochString ());
}
}
else
@ -581,14 +581,14 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string
if (formatted != value)
{
context.footnote (STRING_EDIT_WAIT_MOD);
task.set ("wait", Date(value, dateformat).toEpochString ());
task.set ("wait", ISO8601d (value, dateformat).toEpochString ());
task.setStatus (Task::waiting);
}
}
else
{
context.footnote (STRING_EDIT_WAIT_MOD);
task.set ("wait", Date(value, dateformat).toEpochString ());
task.set ("wait", ISO8601d (value, dateformat).toEpochString ());
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
// 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).
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
// 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 + ":");
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" ||
(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")
{
task.set (col.first, Date (value, dateformat).toEpochString ());
task.set (col.first, ISO8601d (value, dateformat).toEpochString ());
}
else if (type == "duration")
{

View file

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

View file

@ -31,7 +31,6 @@
#include <Context.h>
#include <Filter.h>
#include <ISO8601.h>
#include <Date.h>
#include <main.h>
#include <text.h>
#include <i18n.h>
@ -113,7 +112,7 @@ int CmdInfo::execute (std::string& output)
view.colorHeader (label);
}
Date now;
ISO8601d now;
// id
int row = view.addRow ();
@ -133,7 +132,7 @@ int CmdInfo::execute (std::string& output)
for (auto& anno : annotations)
description += "\n"
+ std::string (indent, ' ')
+ Date (anno.first.substr (11)).toString (dateformatanno)
+ ISO8601d (anno.first.substr (11)).toString (dateformatanno)
+ " "
+ anno.second;
@ -221,14 +220,14 @@ int CmdInfo::execute (std::string& output)
// entry
row = view.addRow ();
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 age;
std::string created = task.get ("entry");
if (created.length ())
{
Date dt (strtol (created.c_str (), NULL, 10));
ISO8601d dt (strtol (created.c_str (), NULL, 10));
age = ISO8601p (now - dt).formatVague ();
}
@ -239,7 +238,7 @@ int CmdInfo::execute (std::string& output)
{
row = view.addRow ();
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
@ -247,7 +246,7 @@ int CmdInfo::execute (std::string& output)
{
row = view.addRow ();
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
@ -255,7 +254,7 @@ int CmdInfo::execute (std::string& output)
{
row = view.addRow ();
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)
@ -263,7 +262,7 @@ int CmdInfo::execute (std::string& output)
{
row = view.addRow ();
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
@ -271,7 +270,7 @@ int CmdInfo::execute (std::string& output)
{
row = view.addRow ();
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
@ -279,7 +278,7 @@ int CmdInfo::execute (std::string& output)
{
row = view.addRow ();
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
@ -288,7 +287,7 @@ int CmdInfo::execute (std::string& output)
row = view.addRow ();
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 ();
view.set (row, 1, mod.toString (dateformat) + " (" + age + ")");
}
@ -373,13 +372,13 @@ int CmdInfo::execute (std::string& output)
view.set (row, 0, col->label ());
if (type == "date")
value = Date (value).toString (dateformat);
value = ISO8601d (value).toString (dateformat);
else if (type == "duration")
{
ISO8601p iso;
std::string::size_type cursor = 0;
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
value = "PT0S";
}
@ -544,7 +543,7 @@ int CmdInfo::execute (std::string& output)
{
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));
Task before (previous.substr (4));

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

1
test/.gitignore vendored
View file

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

View file

@ -9,15 +9,15 @@ include_directories (${CMAKE_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/test
${TASK_INCLUDE_DIRS})
set (test_SRCS autocomplete.t col.t color.t config.t date.t fs.t i18n.t json.t
list.t msg.t nibbler.t rx.t t.t t2.t t3.t tdb2.t text.t utf8.t
util.t view.t json_test lexer.t iso8601d.t iso8601p.t eval.t
set (test_SRCS autocomplete.t col.t color.t config.t fs.t i18n.t json.t list.t
msg.t nibbler.t rx.t t.t t2.t t3.t tdb2.t text.t utf8.t util.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_equal.t variant_exp.t variant_gt.t variant_gte.t
variant_inequal.t variant_lt.t variant_lte.t variant_match.t
variant_math.t variant_modulo.t variant_multiply.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
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_offset,
bool in_utc,
time_t in_value)
time_t in_date)
{
std::string label = std::string ("parse (\"") + input + "\") --> ";
@ -65,13 +65,13 @@ void testParse (
t.is (iso._seconds, in_seconds, label + "_seconds");
t.is (iso._offset, in_offset, label + "_offset");
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)
{
UnitTest t (758);
UnitTest t (904);
ISO8601d iso;
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, "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;
}

View file

@ -44,7 +44,7 @@ void testParse (
int in_hours,
int in_minutes,
int in_seconds,
time_t in_value,
time_t in_period,
const std::string& output,
const std::string& vague)
{
@ -61,7 +61,7 @@ void testParse (
t.is (iso._hours, in_hours, label + "_hours");
t.is (iso._minutes, in_minutes, label + "_minutes");
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.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 }, },
// 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 }, },
// Identifier
@ -348,9 +346,6 @@ int main (int argc, char** argv)
{ "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 }, },
// 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.
{ "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 }, },
{ "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 }, },
{ "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
{ "year", { { "year", Lexer::Type::duration }, NO, NO, NO, NO }, },

View file

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

View file

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