added inclusion specifiers: -z june, -z 2004, -z "monthly in 2003", etc.
This commit is contained in:
parent
5ab3b21396
commit
9d1bdd0989
4 changed files with 129 additions and 59 deletions
10
config.cc
10
config.cc
|
|
@ -160,23 +160,23 @@ OPT_BEGIN(set_price, "p:") {
|
||||||
OPT_BEGIN(begin_date, "b:") {
|
OPT_BEGIN(begin_date, "b:") {
|
||||||
if (! config->predicate.empty())
|
if (! config->predicate.empty())
|
||||||
config->predicate += "&";
|
config->predicate += "&";
|
||||||
config->predicate += "(d>=[";
|
config->predicate += "d>=[";
|
||||||
config->predicate += optarg;
|
config->predicate += optarg;
|
||||||
config->predicate += "])";
|
config->predicate += "]";
|
||||||
} OPT_END(begin_date);
|
} OPT_END(begin_date);
|
||||||
|
|
||||||
OPT_BEGIN(end_date, "e:") {
|
OPT_BEGIN(end_date, "e:") {
|
||||||
if (! config->predicate.empty())
|
if (! config->predicate.empty())
|
||||||
config->predicate += "&";
|
config->predicate += "&";
|
||||||
config->predicate += "(d<[";
|
config->predicate += "d<[";
|
||||||
config->predicate += optarg;
|
config->predicate += optarg;
|
||||||
config->predicate += "])";
|
config->predicate += "]";
|
||||||
} OPT_END(end_date);
|
} OPT_END(end_date);
|
||||||
|
|
||||||
OPT_BEGIN(current, "c") {
|
OPT_BEGIN(current, "c") {
|
||||||
if (! config->predicate.empty())
|
if (! config->predicate.empty())
|
||||||
config->predicate += "&";
|
config->predicate += "&";
|
||||||
config->predicate += "(d<=N)";
|
config->predicate += "d<=N";
|
||||||
} OPT_END(current);
|
} OPT_END(current);
|
||||||
|
|
||||||
OPT_BEGIN(cleared, "C") {
|
OPT_BEGIN(cleared, "C") {
|
||||||
|
|
|
||||||
122
datetime.cc
122
datetime.cc
|
|
@ -1,4 +1,5 @@
|
||||||
#include "datetime.h"
|
#include "datetime.h"
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
|
@ -51,56 +52,109 @@ std::time_t interval_t::increment(const std::time_t moment)
|
||||||
return then + seconds;
|
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 years = 0;
|
||||||
unsigned long months = 0;
|
unsigned long months = 0;
|
||||||
unsigned long seconds = 0;
|
unsigned long seconds = 0;
|
||||||
|
|
||||||
std::string word;
|
std::string word;
|
||||||
in >> word;
|
while (! in.eof()) {
|
||||||
if (word == "every") {
|
|
||||||
in >> word;
|
in >> word;
|
||||||
if (std::isdigit(word[0])) {
|
if (word == "every") {
|
||||||
int quantity = std::atol(word.c_str());
|
|
||||||
in >> word;
|
in >> word;
|
||||||
if (word == "days")
|
if (std::isdigit(word[0])) {
|
||||||
seconds = 86400 * quantity;
|
int quantity = std::atol(word.c_str());
|
||||||
else if (word == "weeks")
|
in >> word;
|
||||||
seconds = 7 * 86400 * quantity;
|
if (word == "days")
|
||||||
else if (word == "months")
|
seconds = 86400 * quantity;
|
||||||
months = quantity;
|
else if (word == "weeks")
|
||||||
else if (word == "quarters")
|
seconds = 7 * 86400 * quantity;
|
||||||
months = 3 * quantity;
|
else if (word == "months")
|
||||||
else if (word == "years")
|
months = quantity;
|
||||||
years = 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;
|
seconds = 86400;
|
||||||
else if (word == "week")
|
else if (word == "weekly")
|
||||||
seconds = 7 * 86400;
|
seconds = 7 * 86400;
|
||||||
|
else if (word == "biweekly")
|
||||||
|
seconds = 14 * 86400;
|
||||||
else if (word == "monthly")
|
else if (word == "monthly")
|
||||||
months = 1;
|
months = 1;
|
||||||
else if (word == "quarter")
|
else if (word == "bimonthly")
|
||||||
|
months = 2;
|
||||||
|
else if (word == "quarterly")
|
||||||
months = 3;
|
months = 3;
|
||||||
else if (word == "year")
|
else if (word == "yearly")
|
||||||
years = 1;
|
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);
|
return new interval_t(seconds, months, years);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,8 @@ struct interval_t
|
||||||
|
|
||||||
std::time_t increment(const std::time_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;
|
extern std::time_t now;
|
||||||
|
|
|
||||||
53
main.cc
53
main.cc
|
|
@ -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
|
// Compile the sorting criteria
|
||||||
|
|
||||||
std::auto_ptr<value_expr_t> sort_order;
|
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)
|
#define OUT() (output_stream.get() ? *output_stream : std::cout)
|
||||||
|
|
||||||
if (! config->interval_text.empty()) {
|
if (! config->interval_text.empty()) {
|
||||||
std::istringstream stream(config->interval_text);
|
try {
|
||||||
report_interval.reset(interval_t::parse(stream));
|
std::istringstream stream(config->interval_text);
|
||||||
if (! stream.eof()) {
|
std::time_t begin = -1, end = -1;
|
||||||
std::string word;
|
report_interval.reset(interval_t::parse(stream, &begin, &end));
|
||||||
stream >> word;
|
if (report_interval->seconds == 0 &&
|
||||||
if (word == "from") {
|
report_interval->months == 0 &&
|
||||||
stream >> word;
|
report_interval->years == 0)
|
||||||
if (! parse_date(word.c_str(), &interval_begin)) {
|
report_interval.release();
|
||||||
std::cerr << "Error in report interval: "
|
|
||||||
<< "Could not parse 'from' date"
|
if (begin != -1) {
|
||||||
<< std::endl;
|
if (! config->predicate.empty())
|
||||||
return 1;
|
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())
|
if (! config->date_format.empty())
|
||||||
format_t::date_format = config->date_format;
|
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
|
// Walk the entries based on the report type and the options
|
||||||
|
|
||||||
TIMER_START(report_gen);
|
TIMER_START(report_gen);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue