interval_t objects now play nicely with python. see the bottom of main.py

This commit is contained in:
John Wiegley 2004-09-10 18:38:52 -04:00
parent e414123ecb
commit e1d6c4bff2
10 changed files with 140 additions and 63 deletions

View file

@ -42,7 +42,6 @@ config_t::config_t()
download_quotes = false; download_quotes = false;
use_cache = false; use_cache = false;
cache_dirty = false; cache_dirty = false;
interval_begin = 0;
} }
static void static void
@ -226,25 +225,22 @@ void config_t::process_options(const std::string& command,
if (! report_interval && ! interval_text.empty()) { if (! report_interval && ! interval_text.empty()) {
try { try {
std::istringstream stream(interval_text); std::istringstream stream(interval_text);
std::time_t begin = -1, end = -1;
report_interval = interval_t::parse(stream, &begin, &end); report_interval.parse(stream);
if (begin != -1) {
interval_begin = begin;
if (report_interval.begin) {
if (! predicate.empty()) if (! predicate.empty())
predicate += "&"; predicate += "&";
char buf[32]; char buf[32];
std::sprintf(buf, "d>=%lu", begin); std::sprintf(buf, "d>=%lu", report_interval.begin);
predicate += buf; predicate += buf;
} }
if (end != -1) { if (report_interval.end) {
if (! predicate.empty()) if (! predicate.empty())
predicate += "&"; predicate += "&";
char buf[32]; char buf[32];
std::sprintf(buf, "d<%lu", end); std::sprintf(buf, "d<%lu", report_interval.end);
predicate += buf; predicate += buf;
} }
} }

View file

@ -55,7 +55,6 @@ struct config_t
bool use_cache; bool use_cache;
bool cache_dirty; bool cache_dirty;
interval_t report_interval; interval_t report_interval;
std::time_t interval_begin;
format_t format; format_t format;
format_t nformat; format_t nformat;

View file

@ -30,6 +30,30 @@ static const char * formats[] = {
NULL NULL
}; };
std::time_t interval_t::first(const std::time_t moment)
{
std::time_t quant = begin;
if (moment && std::difftime(moment, quant) > 0) {
if (! seconds) {
struct std::tm * desc = std::localtime(&moment);
if (years)
desc->tm_mon = 0;
desc->tm_mday = 1;
desc->tm_hour = 0;
desc->tm_min = 0;
desc->tm_sec = 0;
quant = std::mktime(desc);
}
std::time_t temp;
while (std::difftime(moment, temp = increment(quant)) > 0)
quant = temp;
}
return quant;
}
std::time_t interval_t::increment(const std::time_t moment) std::time_t interval_t::increment(const std::time_t moment)
{ {
std::time_t then = moment; std::time_t then = moment;
@ -93,15 +117,10 @@ static void parse_inclusion_specifier(const std::string& word,
saw_year ? 1 : 0).increment(*begin); saw_year ? 1 : 0).increment(*begin);
} }
interval_t interval_t::parse(std::istream& in, void 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; std::string word;
while (! in.eof()) { while (! in.eof()) {
in >> word; in >> word;
if (word == "every") { if (word == "every") {
@ -165,57 +184,47 @@ interval_t interval_t::parse(std::istream& in,
word = buf; word = buf;
} }
parse_inclusion_specifier(word, begin, end); parse_inclusion_specifier(word, &begin, &end);
if (type == "last") { if (type == "last") {
if (mon_spec) { if (mon_spec) {
if (begin) begin = interval_t(0, -1, 0).increment(begin);
*begin = interval_t(0, -1, 0).increment(*begin); end = interval_t(0, -1, 0).increment(end);
if (end)
*end = interval_t(0, -1, 0).increment(*end);
} else { } else {
if (begin) begin = interval_t(0, 0, -1).increment(begin);
*begin = interval_t(0, 0, -1).increment(*begin); end = interval_t(0, 0, -1).increment(end);
if (end)
*end = interval_t(0, 0, -1).increment(*end);
} }
} }
else if (type == "next") { else if (type == "next") {
if (mon_spec) { if (mon_spec) {
if (begin) begin = interval_t(0, 1, 0).increment(begin);
*begin = interval_t(0, 1, 0).increment(*begin); end = interval_t(0, 1, 0).increment(end);
if (end)
*end = interval_t(0, 1, 0).increment(*end);
} else { } else {
if (begin) begin = interval_t(0, 0, 1).increment(begin);
*begin = interval_t(0, 0, 1).increment(*begin); end = interval_t(0, 0, 1).increment(end);
if (end)
*end = interval_t(0, 0, 1).increment(*end);
} }
} }
} }
else if (word == "in") { else if (word == "in") {
in >> word; in >> word;
parse_inclusion_specifier(word, begin, end); parse_inclusion_specifier(word, &begin, &end);
} }
else if (word == "from") { else if (word == "from") {
in >> word; in >> word;
if (! parse_date(word.c_str(), begin)) if (! parse_date(word.c_str(), &begin))
throw interval_expr_error("Could not parse 'from' date"); throw interval_expr_error("Could not parse 'from' date");
if (! in.eof()) if (! in.eof())
in >> word; in >> word;
} }
else if (word == "to") { else if (word == "to") {
in >> word; in >> word;
if (! parse_date(word.c_str(), end)) if (! parse_date(word.c_str(), &end))
throw interval_expr_error("Could not parse 'to' date"); throw interval_expr_error("Could not parse 'to' date");
} }
else { else {
parse_inclusion_specifier(word, begin, end); parse_inclusion_specifier(word, &begin, &end);
} }
} }
return interval_t(seconds, months, years);
} }
bool parse_date_mask(const char * date_str, struct std::tm * result) bool parse_date_mask(const char * date_str, struct std::tm * result)
@ -308,3 +317,63 @@ bool quick_parse_date(char * date_str, std::time_t * result)
} }
} // namespace ledger } // namespace ledger
#ifdef USE_BOOST_PYTHON
#include <boost/python.hpp>
using namespace boost::python;
using namespace ledger;
unsigned int interval_len(interval_t& interval)
{
int periods = 1;
std::time_t when = interval.first();
while (interval.end && when < interval.end) {
when = interval.increment(when);
if (when < interval.end)
periods++;
}
return periods;
}
std::time_t interval_getitem(interval_t& interval, int i)
{
static std::time_t last_index = 0;
static std::time_t last_moment = 0;
if (i == 0) {
last_index = 0;
last_moment = interval.first();
}
else {
last_moment = interval.increment(last_moment);
if (interval.end && last_moment >= interval.end) {
PyErr_SetString(PyExc_IndexError, "Index out of range");
throw_error_already_set();
}
}
return last_moment;
}
void export_datetime()
{
class_< interval_t >
("Interval", init<optional<int, int, int, std::time_t, std::time_t> >())
.def(init<std::string>())
.def(! self)
.def_readwrite("years", &interval_t::years)
.def_readwrite("months", &interval_t::months)
.def_readwrite("seconds", &interval_t::seconds)
.def_readwrite("begin", &interval_t::begin)
.def_readwrite("end", &interval_t::end)
.def("__len__", interval_len)
.def("__getitem__", interval_getitem)
.def("increment", &interval_t::increment)
;
}
#endif // USE_BOOST_PYTHON

View file

@ -4,19 +4,30 @@
#include "ledger.h" #include "ledger.h"
#include <ctime> #include <ctime>
#include <sstream>
namespace ledger { namespace ledger {
struct interval_t struct interval_t
{ {
int years; unsigned int years;
int months; unsigned int months;
int seconds; unsigned int seconds;
std::time_t begin;
std::time_t end;
interval_t(int _seconds = 0, int _months = 0, int _years = 0) interval_t(int _seconds = 0, int _months = 0, int _years = 0,
: years(_years), months(_months), seconds(_seconds) { std::time_t _begin = 0, std::time_t _end = 0)
: years(_years), months(_months), seconds(_seconds),
begin(_begin), end(_end) {
DEBUG_PRINT("ledger.memory.ctors", "ctor interval_t"); DEBUG_PRINT("ledger.memory.ctors", "ctor interval_t");
} }
interval_t(const std::string& desc)
: years(0), months(0), seconds(0), begin(0), end(0){
DEBUG_PRINT("ledger.memory.ctors", "ctor interval_t");
std::istringstream stream(desc);
parse(stream);
}
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
~interval_t() { ~interval_t() {
DEBUG_PRINT("ledger.memory.dtors", "dtor interval_t"); DEBUG_PRINT("ledger.memory.dtors", "dtor interval_t");
@ -27,11 +38,10 @@ struct interval_t
return seconds > 0 || months > 0 || years > 0; return seconds > 0 || months > 0 || years > 0;
} }
std::time_t first(const std::time_t moment = 0);
std::time_t increment(const std::time_t); std::time_t increment(const std::time_t);
static interval_t parse(std::istream& in, void parse(std::istream& in);
std::time_t * begin,
std::time_t * end);
}; };
extern std::time_t now; extern std::time_t now;

View file

@ -202,8 +202,7 @@ chain_formatters(const std::string& command,
else if (config.report_interval) else if (config.report_interval)
ptrs.push_back(formatter = ptrs.push_back(formatter =
new interval_transactions(formatter, new interval_transactions(formatter,
config.report_interval, config.report_interval));
config.interval_begin));
else if (config.days_of_the_week) else if (config.days_of_the_week)
ptrs.push_back(formatter = new dow_transactions(formatter)); ptrs.push_back(formatter = new dow_transactions(formatter));
} }

View file

@ -1,5 +1,6 @@
import sys import sys
import os import os
import time
from ledger import * from ledger import *
@ -29,3 +30,7 @@ handler = FilterTransactions (handler, "/Checking/")
for entry in journal: for entry in journal:
for xact in entry: for xact in entry:
handler (xact) handler (xact)
span = Interval ("monthly last year")
for date in span:
print time.strftime ("%c", time.localtime (date))

View file

@ -19,6 +19,7 @@ void export_gnucash();
void export_option(); void export_option();
void export_walk(); void export_walk();
void export_format(); void export_format();
void export_datetime();
BOOST_PYTHON_MODULE(ledger) { BOOST_PYTHON_MODULE(ledger) {
export_amount(); export_amount();
@ -35,4 +36,5 @@ BOOST_PYTHON_MODULE(ledger) {
export_option(); export_option();
export_walk(); export_walk();
export_format(); export_format();
export_datetime();
} }

View file

@ -512,9 +512,8 @@ value_expr_t * parse_value_term(std::istream& in)
node.reset(new value_expr_t(value_expr_t::CONSTANT_T)); node.reset(new value_expr_t(value_expr_t::CONSTANT_T));
std::string datespec = buf; interval_t timespan(buf);
std::istringstream stream(datespec); node->constant_t = timespan.first();
interval_t::parse(stream, &node->constant_t, NULL);
break; break;
} }

View file

@ -256,10 +256,10 @@ void subtotal_transactions::operator()(transaction_t& xact)
void interval_transactions::operator()(transaction_t& xact) void interval_transactions::operator()(transaction_t& xact)
{ {
std::time_t quant = interval.increment(begin); std::time_t quant = interval.increment(interval.begin);
if (std::difftime(xact.entry->date, quant) > 0) { if (std::difftime(xact.entry->date, quant) > 0) {
if (last_xact) { if (last_xact) {
start = begin; start = interval.begin;
finish = quant; finish = quant;
flush(); flush();
} }
@ -279,7 +279,7 @@ void interval_transactions::operator()(transaction_t& xact)
while (std::difftime(xact.entry->date, while (std::difftime(xact.entry->date,
temp = interval.increment(quant)) > 0) temp = interval.increment(quant)) > 0)
quant = temp; quant = temp;
begin = quant; interval.begin = quant;
} }
subtotal_transactions::operator()(xact); subtotal_transactions::operator()(xact);

12
walk.h
View file

@ -379,20 +379,18 @@ class subtotal_transactions : public item_handler<transaction_t>
class interval_transactions : public subtotal_transactions class interval_transactions : public subtotal_transactions
{ {
std::time_t begin;
interval_t interval; interval_t interval;
transaction_t * last_xact; transaction_t * last_xact;
public: public:
interval_transactions(item_handler<transaction_t> * handler, interval_transactions(item_handler<transaction_t> * handler,
const interval_t& _interval, const interval_t& _interval)
const std::time_t _begin = 0) : subtotal_transactions(handler), interval(_interval),
: subtotal_transactions(handler), begin(_begin), last_xact(NULL) {}
interval(_interval), last_xact(NULL) {}
virtual ~interval_transactions() { virtual ~interval_transactions() {
start = begin; start = interval.begin;
finish = interval.increment(begin); finish = interval.increment(interval.begin);
} }
virtual void operator()(transaction_t& xact); virtual void operator()(transaction_t& xact);