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

View file

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

View file

@ -30,6 +30,30 @@ static const char * formats[] = {
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 then = moment;
@ -93,15 +117,10 @@ static void parse_inclusion_specifier(const std::string& word,
saw_year ? 1 : 0).increment(*begin);
}
interval_t interval_t::parse(std::istream& in,
std::time_t * begin,
std::time_t * end)
void interval_t::parse(std::istream& in)
{
unsigned long years = 0;
unsigned long months = 0;
unsigned long seconds = 0;
std::string word;
while (! in.eof()) {
in >> word;
if (word == "every") {
@ -165,57 +184,47 @@ interval_t interval_t::parse(std::istream& in,
word = buf;
}
parse_inclusion_specifier(word, begin, end);
parse_inclusion_specifier(word, &begin, &end);
if (type == "last") {
if (mon_spec) {
if (begin)
*begin = interval_t(0, -1, 0).increment(*begin);
if (end)
*end = interval_t(0, -1, 0).increment(*end);
begin = interval_t(0, -1, 0).increment(begin);
end = interval_t(0, -1, 0).increment(end);
} else {
if (begin)
*begin = interval_t(0, 0, -1).increment(*begin);
if (end)
*end = interval_t(0, 0, -1).increment(*end);
begin = interval_t(0, 0, -1).increment(begin);
end = interval_t(0, 0, -1).increment(end);
}
}
else if (type == "next") {
if (mon_spec) {
if (begin)
*begin = interval_t(0, 1, 0).increment(*begin);
if (end)
*end = interval_t(0, 1, 0).increment(*end);
begin = interval_t(0, 1, 0).increment(begin);
end = interval_t(0, 1, 0).increment(end);
} else {
if (begin)
*begin = interval_t(0, 0, 1).increment(*begin);
if (end)
*end = interval_t(0, 0, 1).increment(*end);
begin = interval_t(0, 0, 1).increment(begin);
end = interval_t(0, 0, 1).increment(end);
}
}
}
else if (word == "in") {
in >> word;
parse_inclusion_specifier(word, begin, end);
parse_inclusion_specifier(word, &begin, &end);
}
else if (word == "from") {
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");
if (! in.eof())
in >> word;
}
else if (word == "to") {
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");
}
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)
@ -308,3 +317,63 @@ bool quick_parse_date(char * date_str, std::time_t * result)
}
} // 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 <ctime>
#include <sstream>
namespace ledger {
struct interval_t
{
int years;
int months;
int seconds;
unsigned int years;
unsigned int months;
unsigned int seconds;
std::time_t begin;
std::time_t end;
interval_t(int _seconds = 0, int _months = 0, int _years = 0)
: years(_years), months(_months), seconds(_seconds) {
interval_t(int _seconds = 0, int _months = 0, int _years = 0,
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");
}
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
~interval_t() {
DEBUG_PRINT("ledger.memory.dtors", "dtor interval_t");
@ -27,11 +38,10 @@ struct interval_t
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);
static interval_t parse(std::istream& in,
std::time_t * begin,
std::time_t * end);
void parse(std::istream& in);
};
extern std::time_t now;

View file

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

View file

@ -1,5 +1,6 @@
import sys
import os
import time
from ledger import *
@ -29,3 +30,7 @@ handler = FilterTransactions (handler, "/Checking/")
for entry in journal:
for xact in entry:
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_walk();
void export_format();
void export_datetime();
BOOST_PYTHON_MODULE(ledger) {
export_amount();
@ -35,4 +36,5 @@ BOOST_PYTHON_MODULE(ledger) {
export_option();
export_walk();
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));
std::string datespec = buf;
std::istringstream stream(datespec);
interval_t::parse(stream, &node->constant_t, NULL);
interval_t timespan(buf);
node->constant_t = timespan.first();
break;
}

View file

@ -256,10 +256,10 @@ void subtotal_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 (last_xact) {
start = begin;
start = interval.begin;
finish = quant;
flush();
}
@ -279,7 +279,7 @@ void interval_transactions::operator()(transaction_t& xact)
while (std::difftime(xact.entry->date,
temp = interval.increment(quant)) > 0)
quant = temp;
begin = quant;
interval.begin = quant;
}
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
{
std::time_t begin;
interval_t interval;
transaction_t * last_xact;
public:
interval_transactions(item_handler<transaction_t> * handler,
const interval_t& _interval,
const std::time_t _begin = 0)
: subtotal_transactions(handler), begin(_begin),
interval(_interval), last_xact(NULL) {}
const interval_t& _interval)
: subtotal_transactions(handler), interval(_interval),
last_xact(NULL) {}
virtual ~interval_transactions() {
start = begin;
finish = interval.increment(begin);
start = interval.begin;
finish = interval.increment(interval.begin);
}
virtual void operator()(transaction_t& xact);