added inclusion specifiers: -z june, -z 2004, -z "monthly in 2003", etc.

This commit is contained in:
John Wiegley 2004-08-18 01:20:01 -04:00
parent 5ab3b21396
commit 9d1bdd0989
4 changed files with 129 additions and 59 deletions

View file

@ -160,23 +160,23 @@ OPT_BEGIN(set_price, "p:") {
OPT_BEGIN(begin_date, "b:") {
if (! config->predicate.empty())
config->predicate += "&";
config->predicate += "(d>=[";
config->predicate += "d>=[";
config->predicate += optarg;
config->predicate += "])";
config->predicate += "]";
} OPT_END(begin_date);
OPT_BEGIN(end_date, "e:") {
if (! config->predicate.empty())
config->predicate += "&";
config->predicate += "(d<[";
config->predicate += "d<[";
config->predicate += optarg;
config->predicate += "])";
config->predicate += "]";
} OPT_END(end_date);
OPT_BEGIN(current, "c") {
if (! config->predicate.empty())
config->predicate += "&";
config->predicate += "(d<=N)";
config->predicate += "d<=N";
} OPT_END(current);
OPT_BEGIN(cleared, "C") {

View file

@ -1,4 +1,5 @@
#include "datetime.h"
#include "error.h"
#include <ctime>
@ -51,56 +52,109 @@ std::time_t interval_t::increment(const std::time_t moment)
return then + seconds;
}
interval_t * interval_t::parse(std::istream& in)
static void parse_inclusion_specifier(const std::string& word,
std::time_t * begin,
std::time_t * end)
{
struct std::tm when;
if (! parse_date_mask(word.c_str(), &when))
throw interval_expr_error("Could not parse 'in' date mask");
when.tm_hour = 0;
when.tm_min = 0;
when.tm_sec = 0;
bool saw_year = true;
bool saw_mon = true;
if (when.tm_year == -1) {
when.tm_year = now_tm->tm_year;
saw_year = false;
}
if (when.tm_mon == -1) {
when.tm_mon = 0;
saw_mon = false;
}
if (when.tm_mday == -1)
when.tm_mday = 1;
*begin = std::mktime(&when);
*end = interval_t(0, saw_mon ? 1 : 0, saw_year ? 1 : 0).increment(*begin);
}
interval_t * interval_t::parse(std::istream& in,
std::time_t * begin,
std::time_t * end)
{
unsigned long years = 0;
unsigned long months = 0;
unsigned long seconds = 0;
std::string word;
in >> word;
if (word == "every") {
while (! in.eof()) {
in >> word;
if (std::isdigit(word[0])) {
int quantity = std::atol(word.c_str());
if (word == "every") {
in >> word;
if (word == "days")
seconds = 86400 * quantity;
else if (word == "weeks")
seconds = 7 * 86400 * quantity;
else if (word == "months")
months = quantity;
else if (word == "quarters")
months = 3 * quantity;
else if (word == "years")
years = quantity;
if (std::isdigit(word[0])) {
int quantity = std::atol(word.c_str());
in >> word;
if (word == "days")
seconds = 86400 * quantity;
else if (word == "weeks")
seconds = 7 * 86400 * quantity;
else if (word == "months")
months = quantity;
else if (word == "quarters")
months = 3 * quantity;
else if (word == "years")
years = quantity;
}
else if (word == "day")
seconds = 86400;
else if (word == "week")
seconds = 7 * 86400;
else if (word == "monthly")
months = 1;
else if (word == "quarter")
months = 3;
else if (word == "year")
years = 1;
}
else if (word == "day")
else if (word == "daily")
seconds = 86400;
else if (word == "week")
else if (word == "weekly")
seconds = 7 * 86400;
else if (word == "biweekly")
seconds = 14 * 86400;
else if (word == "monthly")
months = 1;
else if (word == "quarter")
else if (word == "bimonthly")
months = 2;
else if (word == "quarterly")
months = 3;
else if (word == "year")
else if (word == "yearly")
years = 1;
else if (word == "in") {
in >> word;
parse_inclusion_specifier(word, begin, end);
}
else if (word == "from") {
in >> word;
if (! parse_date(word.c_str(), begin))
throw interval_expr_error("Could not parse 'from' date");
if (! in.eof())
in >> word;
}
else if (word == "to") {
in >> word;
if (! parse_date(word.c_str(), end))
throw interval_expr_error("Could not parse 'to' date");
}
else {
parse_inclusion_specifier(word, begin, end);
}
}
else if (word == "daily")
seconds = 86400;
else if (word == "weekly")
seconds = 7 * 86400;
else if (word == "biweekly")
seconds = 14 * 86400;
else if (word == "monthly")
months = 1;
else if (word == "bimonthly")
months = 2;
else if (word == "quarterly")
months = 3;
else if (word == "yearly")
years = 1;
return new interval_t(seconds, months, years);
}

View file

@ -19,7 +19,8 @@ struct interval_t
std::time_t increment(const std::time_t);
static interval_t * parse(std::istream& in);
static interval_t * parse(std::istream& in, std::time_t * begin,
std::time_t * end);
};
extern std::time_t now;

53
main.cc
View file

@ -295,12 +295,6 @@ int main(int argc, char * argv[], char * envp[])
}
}
#ifdef DEBUG_ENABLED
DEBUG_PRINT("ledger.main.predicates", "predicate: " << config->predicate);
DEBUG_PRINT("ledger.main.predicates",
"disp-pred: " << config->display_predicate);
#endif
// Compile the sorting criteria
std::auto_ptr<value_expr_t> sort_order;
@ -418,26 +412,47 @@ int main(int argc, char * argv[], char * envp[])
#define OUT() (output_stream.get() ? *output_stream : std::cout)
if (! config->interval_text.empty()) {
std::istringstream stream(config->interval_text);
report_interval.reset(interval_t::parse(stream));
if (! stream.eof()) {
std::string word;
stream >> word;
if (word == "from") {
stream >> word;
if (! parse_date(word.c_str(), &interval_begin)) {
std::cerr << "Error in report interval: "
<< "Could not parse 'from' date"
<< std::endl;
return 1;
}
try {
std::istringstream stream(config->interval_text);
std::time_t begin = -1, end = -1;
report_interval.reset(interval_t::parse(stream, &begin, &end));
if (report_interval->seconds == 0 &&
report_interval->months == 0 &&
report_interval->years == 0)
report_interval.release();
if (begin != -1) {
if (! config->predicate.empty())
config->predicate += "&";
char buf[32];
std::sprintf(buf, "d>=%lu", begin);
config->predicate += buf;
}
if (end != -1) {
if (! config->predicate.empty())
config->predicate += "&";
char buf[32];
std::sprintf(buf, "d<%lu", end);
config->predicate += buf;
}
}
catch (const interval_expr_error& err) {
std::cerr << "Error in interval (-z) specifier: " << err.what()
<< std::endl;
return 1;
}
}
if (! config->date_format.empty())
format_t::date_format = config->date_format;
#ifdef DEBUG_ENABLED
DEBUG_PRINT("ledger.main.predicates", "predicate: " << config->predicate);
DEBUG_PRINT("ledger.main.predicates",
"disp-pred: " << config->display_predicate);
#endif
// Walk the entries based on the report type and the options
TIMER_START(report_gen);