more time interval support: last month, last feb, next year, etc.

This commit is contained in:
John Wiegley 2004-08-18 02:15:31 -04:00
parent 9d1bdd0989
commit 8af33274fb
8 changed files with 101 additions and 54 deletions

View file

@ -5,8 +5,8 @@
namespace ledger { namespace ledger {
std::time_t now = std::time(NULL); std::time_t now = std::time(NULL);
struct std::tm * now_tm = std::localtime(&now); int now_year = std::localtime(&now)->tm_year;
static std::time_t base = -1; static std::time_t base = -1;
static int base_year = -1; static int base_year = -1;
@ -35,9 +35,11 @@ std::time_t interval_t::increment(const std::time_t moment)
std::time_t then = moment; std::time_t then = moment;
if (years || months) { if (years || months) {
struct std::tm * desc = std::gmtime(&then); struct std::tm * desc = std::localtime(&then);
if (years) if (years)
desc->tm_year += years; desc->tm_year += years;
if (months) { if (months) {
desc->tm_mon += months; desc->tm_mon += months;
@ -45,7 +47,12 @@ std::time_t interval_t::increment(const std::time_t moment)
desc->tm_year++; desc->tm_year++;
desc->tm_mon -= 12; desc->tm_mon -= 12;
} }
else if (desc->tm_mon < 0) {
desc->tm_year--;
desc->tm_mon += 12;
}
} }
then = std::mktime(desc); then = std::mktime(desc);
} }
@ -69,7 +76,7 @@ static void parse_inclusion_specifier(const std::string& word,
bool saw_mon = true; bool saw_mon = true;
if (when.tm_year == -1) { if (when.tm_year == -1) {
when.tm_year = now_tm->tm_year; when.tm_year = now_year;
saw_year = false; saw_year = false;
} }
if (when.tm_mon == -1) { if (when.tm_mon == -1) {
@ -135,6 +142,47 @@ interval_t * interval_t::parse(std::istream& in,
months = 3; months = 3;
else if (word == "yearly") else if (word == "yearly")
years = 1; years = 1;
else if (word == "this" || word == "last" || word == "next") {
std::string type = word;
bool mon_spec = false;
char buf[32];
if (! in.eof())
in >> word;
else
word = "month";
if (word == "month") {
std::strftime(buf, 31, "%B", std::localtime(&now));
word = buf;
mon_spec = true;
}
else if (word == "year") {
std::strftime(buf, 31, "%Y", std::localtime(&now));
word = buf;
}
parse_inclusion_specifier(word, begin, end);
if (type == "last") {
if (mon_spec) {
*begin = interval_t(0, -1, 0).increment(*begin);
*end = interval_t(0, -1, 0).increment(*end);
} else {
*begin = interval_t(0, 0, -1).increment(*begin);
*end = interval_t(0, 0, -1).increment(*end);
}
}
else if (type == "next") {
if (mon_spec) {
*begin = interval_t(0, 1, 0).increment(*begin);
*end = interval_t(0, 1, 0).increment(*end);
} else {
*begin = interval_t(0, 0, 1).increment(*begin);
*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);
@ -180,7 +228,7 @@ bool parse_date(const char * date_str, std::time_t * result, const int year)
when.tm_sec = 0; when.tm_sec = 0;
if (when.tm_year == -1) if (when.tm_year == -1)
when.tm_year = ((year == -1) ? now_tm->tm_year : (year - 1900)); when.tm_year = ((year == -1) ? now_year : (year - 1900));
if (when.tm_mon == -1) if (when.tm_mon == -1)
when.tm_mon = 0; when.tm_mon = 0;
@ -225,8 +273,8 @@ bool quick_parse_date(char * date_str, std::time_t * result)
struct std::tm when; struct std::tm when;
std::memset(&when, 0, sizeof(when)); std::memset(&when, 0, sizeof(when));
base_year = year == -1 ? now_tm->tm_year + 1900 : year; base_year = year == -1 ? now_year + 1900 : year;
when.tm_year = year == -1 ? now_tm->tm_year : year - 1900; when.tm_year = year == -1 ? now_year : year - 1900;
when.tm_mday = 1; when.tm_mday = 1;
base = std::mktime(&when); base = std::mktime(&when);

View file

@ -9,12 +9,11 @@ namespace ledger {
struct interval_t struct interval_t
{ {
unsigned long years; int years;
unsigned long months; int months;
unsigned long seconds; int seconds;
interval_t(unsigned long _seconds, unsigned long _months = 0, interval_t(int _seconds, int _months = 0, int _years = 0)
unsigned long _years = 0)
: years(_years), months(_months), seconds(_seconds) {} : years(_years), months(_months), seconds(_seconds) {}
std::time_t increment(const std::time_t); std::time_t increment(const std::time_t);
@ -23,8 +22,8 @@ struct interval_t
std::time_t * end); std::time_t * end);
}; };
extern std::time_t now; extern std::time_t now;
extern struct std::tm * now_tm; extern int now_year;
bool parse_date_mask(const char * date_str, struct std::tm * result); bool parse_date_mask(const char * date_str, struct std::tm * result);

View file

@ -92,10 +92,10 @@ inline bool _debug_active(const char * const cls) {
} }
#define DEBUG_PRINT_(x) DEBUG_PRINT(_debug_cls, x) #define DEBUG_PRINT_(x) DEBUG_PRINT(_debug_cls, x)
#define DEBUG_PRINT_TIME(cls, x) { \ #define DEBUG_PRINT_TIME(cls, x) { \
char buf[256]; \ char buf[256]; \
std::strftime(buf, 255, "%Y/%m/%d", std::gmtime(&x)); \ std::strftime(buf, 255, "%Y/%m/%d", std::localtime(&x)); \
DEBUG_PRINT(cls, #x << " is " << buf); \ DEBUG_PRINT(cls, #x << " is " << buf); \
} }
#define DEBUG_PRINT_TIME_(x) DEBUG_PRINT_TIME(_debug_cls, x) #define DEBUG_PRINT_TIME_(x) DEBUG_PRINT_TIME(_debug_cls, x)

View file

@ -223,7 +223,7 @@ void format_t::format_elements(std::ostream& out,
if (details.entry && details.entry->date != -1) { if (details.entry && details.entry->date != -1) {
char buf[256]; char buf[256];
std::strftime(buf, 255, elem->chars.c_str(), std::strftime(buf, 255, elem->chars.c_str(),
std::gmtime(&details.entry->date)); std::localtime(&details.entry->date));
out << (elem->max_width == 0 ? buf : truncated(buf, elem->max_width)); out << (elem->max_width == 0 ? buf : truncated(buf, elem->max_width));
} else { } else {
out << " "; out << " ";

58
main.cc
View file

@ -365,35 +365,6 @@ int main(int argc, char * argv[], char * envp[])
show_all_related = true; show_all_related = true;
} }
// Compile the format strings
const char * f;
if (! config->format_string.empty())
f = config->format_string.c_str();
else if (command == "b")
f = bal_fmt.c_str();
else if (command == "r")
f = reg_fmt.c_str();
else if (command == "E")
f = equity_fmt.c_str();
else
f = print_fmt.c_str();
std::string first_line_format;
std::string next_lines_format;
if (const char * p = std::strstr(f, "%/")) {
first_line_format = std::string(f, 0, p - f);
next_lines_format = std::string(p + 2);
} else {
first_line_format = next_lines_format = f;
}
format_t format(first_line_format);
format_t nformat(next_lines_format);
TIMER_STOP(handle_options);
// Setup a few local and global variables, depending on the config // Setup a few local and global variables, depending on the config
// settings. // settings.
@ -453,6 +424,35 @@ int main(int argc, char * argv[], char * envp[])
"disp-pred: " << config->display_predicate); "disp-pred: " << config->display_predicate);
#endif #endif
// Compile the format strings
const char * f;
if (! config->format_string.empty())
f = config->format_string.c_str();
else if (command == "b")
f = bal_fmt.c_str();
else if (command == "r")
f = reg_fmt.c_str();
else if (command == "E")
f = equity_fmt.c_str();
else
f = print_fmt.c_str();
std::string first_line_format;
std::string next_lines_format;
if (const char * p = std::strstr(f, "%/")) {
first_line_format = std::string(f, 0, p - f);
next_lines_format = std::string(p + 2);
} else {
first_line_format = next_lines_format = f;
}
format_t format(first_line_format);
format_t nformat(next_lines_format);
TIMER_STOP(handle_options);
// 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);

View file

@ -476,8 +476,8 @@ unsigned int parse_textual_journal(std::istream& in, journal_t * journal,
case 'Y': // set the current year case 'Y': // set the current year
in >> c; in >> c;
in >> now_tm->tm_year; in >> now_year;
now_tm->tm_year -= 1900; now_year -= 1900;
break; break;
#ifdef TIMELOG_SUPPORT #ifdef TIMELOG_SUPPORT

View file

@ -132,9 +132,9 @@ void subtotal_transactions::flush(const char * spec_fmt)
if (start != finish) if (start != finish)
finish -= 86400; finish -= 86400;
std::strftime(buf, 255, fmt.c_str(), std::gmtime(&finish)); std::strftime(buf, 255, fmt.c_str(), std::localtime(&finish));
} else { } else {
std::strftime(buf, 255, spec_fmt, std::gmtime(&finish)); std::strftime(buf, 255, spec_fmt, std::localtime(&finish));
} }
entry_t * entry = new entry_t; entry_t * entry = new entry_t;
@ -199,7 +199,7 @@ void interval_transactions::operator()(transaction_t * xact)
} }
if (! interval.seconds) { if (! interval.seconds) {
struct std::tm * desc = std::gmtime(&xact->entry->date); struct std::tm * desc = std::localtime(&xact->entry->date);
if (interval.years) if (interval.years)
desc->tm_mon = 0; desc->tm_mon = 0;
desc->tm_mday = 1; desc->tm_mday = 1;

2
walk.h
View file

@ -327,7 +327,7 @@ class dow_transactions : public subtotal_transactions
virtual void flush(); virtual void flush();
virtual void operator()(transaction_t * xact) { virtual void operator()(transaction_t * xact) {
struct std::tm * desc = std::gmtime(&xact->entry->date); struct std::tm * desc = std::localtime(&xact->entry->date);
days_of_the_week[desc->tm_wday].push_back(xact); days_of_the_week[desc->tm_wday].push_back(xact);
} }
}; };