more time interval support: last month, last feb, next year, etc.
This commit is contained in:
parent
9d1bdd0989
commit
8af33274fb
8 changed files with 101 additions and 54 deletions
60
datetime.cc
60
datetime.cc
|
|
@ -6,7 +6,7 @@
|
|||
namespace ledger {
|
||||
|
||||
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 int base_year = -1;
|
||||
|
|
@ -35,9 +35,11 @@ std::time_t interval_t::increment(const std::time_t moment)
|
|||
std::time_t then = moment;
|
||||
|
||||
if (years || months) {
|
||||
struct std::tm * desc = std::gmtime(&then);
|
||||
struct std::tm * desc = std::localtime(&then);
|
||||
|
||||
if (years)
|
||||
desc->tm_year += years;
|
||||
|
||||
if (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_mon -= 12;
|
||||
}
|
||||
else if (desc->tm_mon < 0) {
|
||||
desc->tm_year--;
|
||||
desc->tm_mon += 12;
|
||||
}
|
||||
}
|
||||
|
||||
then = std::mktime(desc);
|
||||
}
|
||||
|
||||
|
|
@ -69,7 +76,7 @@ static void parse_inclusion_specifier(const std::string& word,
|
|||
bool saw_mon = true;
|
||||
|
||||
if (when.tm_year == -1) {
|
||||
when.tm_year = now_tm->tm_year;
|
||||
when.tm_year = now_year;
|
||||
saw_year = false;
|
||||
}
|
||||
if (when.tm_mon == -1) {
|
||||
|
|
@ -135,6 +142,47 @@ interval_t * interval_t::parse(std::istream& in,
|
|||
months = 3;
|
||||
else if (word == "yearly")
|
||||
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") {
|
||||
in >> word;
|
||||
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;
|
||||
|
||||
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)
|
||||
when.tm_mon = 0;
|
||||
|
|
@ -225,8 +273,8 @@ bool quick_parse_date(char * date_str, std::time_t * result)
|
|||
struct std::tm when;
|
||||
std::memset(&when, 0, sizeof(when));
|
||||
|
||||
base_year = year == -1 ? now_tm->tm_year + 1900 : year;
|
||||
when.tm_year = year == -1 ? now_tm->tm_year : year - 1900;
|
||||
base_year = year == -1 ? now_year + 1900 : year;
|
||||
when.tm_year = year == -1 ? now_year : year - 1900;
|
||||
when.tm_mday = 1;
|
||||
|
||||
base = std::mktime(&when);
|
||||
|
|
|
|||
11
datetime.h
11
datetime.h
|
|
@ -9,12 +9,11 @@ namespace ledger {
|
|||
|
||||
struct interval_t
|
||||
{
|
||||
unsigned long years;
|
||||
unsigned long months;
|
||||
unsigned long seconds;
|
||||
int years;
|
||||
int months;
|
||||
int seconds;
|
||||
|
||||
interval_t(unsigned long _seconds, unsigned long _months = 0,
|
||||
unsigned long _years = 0)
|
||||
interval_t(int _seconds, int _months = 0, int _years = 0)
|
||||
: years(_years), months(_months), seconds(_seconds) {}
|
||||
|
||||
std::time_t increment(const std::time_t);
|
||||
|
|
@ -24,7 +23,7 @@ struct interval_t
|
|||
};
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
|||
2
debug.h
2
debug.h
|
|
@ -94,7 +94,7 @@ inline bool _debug_active(const char * const cls) {
|
|||
|
||||
#define DEBUG_PRINT_TIME(cls, x) { \
|
||||
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); \
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ void format_t::format_elements(std::ostream& out,
|
|||
if (details.entry && details.entry->date != -1) {
|
||||
char buf[256];
|
||||
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));
|
||||
} else {
|
||||
out << " ";
|
||||
|
|
|
|||
58
main.cc
58
main.cc
|
|
@ -365,35 +365,6 @@ int main(int argc, char * argv[], char * envp[])
|
|||
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
|
||||
// settings.
|
||||
|
||||
|
|
@ -453,6 +424,35 @@ int main(int argc, char * argv[], char * envp[])
|
|||
"disp-pred: " << config->display_predicate);
|
||||
#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
|
||||
|
||||
TIMER_START(report_gen);
|
||||
|
|
|
|||
|
|
@ -476,8 +476,8 @@ unsigned int parse_textual_journal(std::istream& in, journal_t * journal,
|
|||
|
||||
case 'Y': // set the current year
|
||||
in >> c;
|
||||
in >> now_tm->tm_year;
|
||||
now_tm->tm_year -= 1900;
|
||||
in >> now_year;
|
||||
now_year -= 1900;
|
||||
break;
|
||||
|
||||
#ifdef TIMELOG_SUPPORT
|
||||
|
|
|
|||
6
walk.cc
6
walk.cc
|
|
@ -132,9 +132,9 @@ void subtotal_transactions::flush(const char * spec_fmt)
|
|||
if (start != finish)
|
||||
finish -= 86400;
|
||||
|
||||
std::strftime(buf, 255, fmt.c_str(), std::gmtime(&finish));
|
||||
std::strftime(buf, 255, fmt.c_str(), std::localtime(&finish));
|
||||
} 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;
|
||||
|
|
@ -199,7 +199,7 @@ void interval_transactions::operator()(transaction_t * xact)
|
|||
}
|
||||
|
||||
if (! interval.seconds) {
|
||||
struct std::tm * desc = std::gmtime(&xact->entry->date);
|
||||
struct std::tm * desc = std::localtime(&xact->entry->date);
|
||||
if (interval.years)
|
||||
desc->tm_mon = 0;
|
||||
desc->tm_mday = 1;
|
||||
|
|
|
|||
2
walk.h
2
walk.h
|
|
@ -327,7 +327,7 @@ class dow_transactions : public subtotal_transactions
|
|||
|
||||
virtual void flush();
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue