summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.cc25
-rw-r--r--times.cc198
-rw-r--r--times.h136
-rw-r--r--walk.cc11
-rw-r--r--walk.h4
5 files changed, 154 insertions, 220 deletions
diff --git a/main.cc b/main.cc
index da5ec84f..f58578fd 100644
--- a/main.cc
+++ b/main.cc
@@ -222,6 +222,31 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[],
fmt.dump(*out);
return 0;
}
+ else if (verb == "period") {
+ interval_t interval(*arg);
+
+ if (! is_valid(interval.begin)) {
+ *out << "Time period has no beginning." << std::endl;
+ } else {
+ *out << "begin: " << format_date(interval.begin) << std::endl;
+ *out << " end: " << format_date(interval.end) << std::endl;
+ *out << std::endl;
+
+ date_t date = interval.first();
+
+ for (int i = 0; i < 20; i++) {
+ *out << std::right;
+ out->width(2);
+
+ *out << i << ": " << format_date(date) << std::endl;
+
+ date = interval.increment(date);
+ if (is_valid(interval.end) && date >= interval.end)
+ break;
+ }
+ }
+ return 0;
+ }
// Parse the initialization file, which can only be textual; then
// parse the journal data.
diff --git a/times.cc b/times.cc
index ccec34fa..97c0c242 100644
--- a/times.cc
+++ b/times.cc
@@ -29,7 +29,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "utils.h"
+#include "utils.h" // this brings in times.h
namespace ledger {
@@ -66,82 +66,92 @@ namespace {
};
}
-string output_time_format = "%Y/%m/%d";
-
-#if 0
-datetime_t datetime_t::now(std::time(NULL));
+optional<string> input_date_format;
+string output_date_format = "%Y/%m/%d";
namespace {
- static std::time_t base = -1;
- static int base_year = -1;
+ bool parse_date_mask(const char * date_str, std::tm& result)
+ {
+ if (input_date_format) {
+ std::memset(&result, -1, sizeof(std::tm));
+ if (strptime(date_str, input_date_format->c_str(), &result))
+ return true;
+ }
+ for (const char ** f = formats; *f; f++) {
+ std::memset(&result, -1, sizeof(std::tm));
+ if (strptime(date_str, *f, &result))
+ return true;
+ }
+ return false;
+ }
- static const int month_days[12] = {
- 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
- };
+ bool parse_date(const char * date_str, std::tm& result, const int year)
+ {
+ if (! parse_date_mask(date_str, result))
+ return false;
+
+ result.tm_hour = 0;
+ result.tm_min = 0;
+ result.tm_sec = 0;
+
+ if (result.tm_year == -1)
+ result.tm_year = ((year == -1) ? current_year : year) - 1900;
+
+ if (result.tm_mon == -1)
+ result.tm_mon = 0;
+
+ if (result.tm_mday == -1)
+ result.tm_mday = 1;
+
+ return true;
+ }
- bool parse_date_mask(const char * date_str, struct std::tm * result);
- bool parse_date(const char * date_str, std::time_t * result,
- const int year = -1);
- bool quick_parse_date(const char * date_str, std::time_t * result);
+ bool quick_parse_date(const char * date_str, std::tm& result)
+ {
+ return parse_date(date_str, result, current_year);
+ }
}
-#endif
datetime_t parse_datetime(const char * str)
{
-#if 0
- return parse_abs_datetime(in);
-#else
- int year = ((str[0] - '0') * 1000 +
- (str[1] - '0') * 100 +
- (str[2] - '0') * 10 +
- (str[3] - '0'));
-
- int mon = ((str[5] - '0') * 10 +
- (str[6] - '0'));
-
- int day = ((str[8] - '0') * 10 +
- (str[9] - '0'));
+ std::tm when;
+ // jww (2008-08-01): This needs to look for HH:MM:SS as well.
+ quick_parse_date(str, when);
+ return posix_time::ptime_from_tm(when);
+}
- return datetime_t(boost::gregorian::date(year, mon, day));
-#endif
+date_t parse_date(const char * str)
+{
+ std::tm when;
+ quick_parse_date(str, when);
+ return gregorian::date_from_tm(when);
}
-date_t interval_t::first(const date_t& moment) const
+date_t interval_t::first(const optional<date_t>& moment) const
{
+ if (! is_valid(begin))
+ throw_(date_error,
+ "Use of interval_t::first() with specifying a range start");
+
date_t quant(begin);
if (! advanced)
advanced = true;
-#if 0
- if (is_valid(moment) && moment > quant) {
+ if (moment && *moment > quant) {
// Find an efficient starting point for the upcoming while loop.
// We want a date early enough that the range will be correct, but
// late enough that we don't spend hundreds of thousands of loops
// skipping through time.
- struct std::tm * desc = std::localtime(&moment.when);
-
- if (years)
- desc->tm_mon = 0;
- desc->tm_mday = 1;
-
- desc->tm_hour = 0;
- desc->tm_min = 0;
- desc->tm_sec = 0;
- desc->tm_isdst = -1;
-
- quant = std::mktime(desc);
-
+ date_t quant(moment->year(), gregorian::Jan, 1);
date_t temp;
- while (moment >= (temp = increment(quant))) {
+ while (*moment >= (temp = increment(quant))) {
if (quant == temp)
break;
quant = temp;
}
}
-#endif
-
return quant;
}
@@ -150,8 +160,8 @@ date_t interval_t::increment(const date_t& moment) const
date_t future(moment);
if (years) future += gregorian::years(years);
- if (months) future += gregorian::years(months);
- if (days) future += gregorian::years(days);
+ if (months) future += gregorian::months(months);
+ if (days) future += gregorian::days(days);
return future;
}
@@ -160,11 +170,9 @@ namespace {
void parse_inclusion_specifier(const string& word,
date_t * begin, date_t * end)
{
-#if 0
- // jww (2008-05-08): Implement!
struct std::tm when;
- if (! parse_date_mask(word.c_str(), &when))
+ if (! parse_date_mask(word.c_str(), when))
throw_(date_error, "Could not parse date mask: " << word);
when.tm_hour = 0;
@@ -177,7 +185,7 @@ namespace {
bool saw_day = true;
if (when.tm_year == -1) {
- when.tm_year = date_t::current_year - 1900;
+ when.tm_year = current_year - 1900;
saw_year = false;
}
if (when.tm_mon == -1) {
@@ -195,19 +203,14 @@ namespace {
}
if (begin) {
- *begin = std::mktime(&when);
- assert(int(*begin) != -1);
- if (end) {
+ *begin = gregorian::date_from_tm(when);
+ if (end)
*end = interval_t(saw_day ? 1 : 0, saw_mon ? 1 : 0,
saw_year ? 1 : 0).increment(*begin);
- assert(int(*end) != -1);
- }
}
else if (end) {
- *end = std::mktime(&when);
- assert(int(*end) != -1);
+ *end = gregorian::date_from_tm(when);
}
-#endif
}
inline void read_lower_word(std::istream& in, string& word) {
@@ -235,18 +238,13 @@ namespace {
}
if (word == "month") {
-#if 0
- // jww (2008-05-08):
- std::strftime(buf, 31, "%B", date_t::now.localtime());
-#endif
+ time_t now = to_time_t(current_time);
+ std::strftime(buf, 31, "%B", localtime(&now));
word = buf;
mon_spec = true;
}
else if (word == "year") {
-#if 0
- // jww (2008-05-08):
- std::strftime(buf, 31, "%Y", date_t::now.localtime());
-#endif
+ std::sprintf(buf, "%04d", current_year);
word = buf;
}
@@ -349,62 +347,4 @@ void interval_t::parse(std::istream& in)
}
}
-namespace {
- bool parse_date_mask(const char * date_str, struct std::tm * result)
- {
-#if 0
- // jww (2008-05-08):
- if (! date_t::input_format.empty()) {
- std::memset(result, -1, sizeof(struct std::tm));
- if (strptime(date_str, date_t::input_format.c_str(), result))
- return true;
- }
- for (const char ** f = formats; *f; f++) {
- std::memset(result, INT_MAX, sizeof(struct std::tm));
- if (strptime(date_str, *f, result))
- return true;
- }
-#endif
- return false;
- }
-
- bool parse_date(const char * date_str, std::time_t * result, const int year)
- {
-#if 0
- // jww (2008-05-08):
- struct std::tm when;
-
- if (! parse_date_mask(date_str, &when))
- return false;
-
- when.tm_hour = 0;
- when.tm_min = 0;
- when.tm_sec = 0;
-
- if (when.tm_year == -1)
- when.tm_year = ((year == -1) ? date_t::current_year : year) - 1900;
-
- if (when.tm_mon == -1)
- when.tm_mon = 0;
-
- if (when.tm_mday == -1)
- when.tm_mday = 1;
-
- *result = std::mktime(&when);
-#endif
-
- return true;
- }
-
- bool quick_parse_date(const char * date_str, std::time_t * result)
- {
-#if 0
- // jww (2008-05-08):
- return parse_date(date_str, result, date_t::current_year);
-#else
- return false;
-#endif
- }
-}
-
} // namespace ledger
diff --git a/times.h b/times.h
index 4ae665be..306477f5 100644
--- a/times.h
+++ b/times.h
@@ -54,41 +54,79 @@ inline bool is_valid(const date_t& moment) {
extern const datetime_t& current_time;
extern const date_t& current_date;
extern int current_year;
-extern string input_time_format;
-extern string output_time_format;
+extern optional<string> input_date_format;
+extern string output_date_format;
+
+inline datetime_t parse_datetime(const string& str) {
+ return parse_datetime(str.c_str());
+}
+datetime_t parse_datetime(const char * str);
+
+inline date_t parse_date(const string& str) {
+ return parse_date(str.c_str());
+}
+date_t parse_date(const char * str);
+
+inline std::time_t to_time_t(const ptime& t)
+{
+ if( t == posix_time::neg_infin )
+ return 0;
+ else if( t == posix_time::pos_infin )
+ return LONG_MAX;
+ ptime start(date(1970,1,1));
+ return (t-start).total_seconds();
+}
+
+inline string format_datetime(const datetime_t& when)
+{
+ char buf[256];
+ time_t moment = to_time_t(when);
+ std::strftime(buf, 255, (output_date_format + " %H:%M:%S").c_str(),
+ std::localtime(&moment));
+ return buf;
+}
+
+inline string format_date(const date_t& when,
+ const optional<string>& format = none)
+{
+ if (format) {
+ char buf[256];
+ std::tm moment = gregorian::to_tm(when);
+ std::strftime(buf, 255, format->c_str(), &moment);
+ return buf;
+ } else {
+ return to_iso_extended_string(when);
+ }
+}
struct interval_t
{
- unsigned short years;
- unsigned short months;
- unsigned short days;
- date_t begin;
- date_t end;
- mutable bool advanced;
+ int years;
+ int months;
+ int days;
+ date_t begin;
+ date_t end;
+
+ mutable bool advanced;
interval_t(int _days = 0, int _months = 0, int _years = 0,
const date_t& _begin = date_t(),
const date_t& _end = date_t())
: years(_years), months(_months), days(_days),
begin(_begin), end(_end), advanced(false) {
- TRACE_CTOR(interval_t,
- "int, int, int, const date_t&, const date_t&");
+ TRACE_CTOR(interval_t, "int, int, int, const date_t&, const date_t&");
}
interval_t(const interval_t& other)
: years(other.years),
months(other.months),
days(other.days),
-
begin(other.begin),
end(other.end),
-
advanced(other.advanced) {
TRACE_CTOR(interval_t, "copy");
}
-
interval_t(const string& desc)
- : years(0), months(0), days(0),
- begin(), end(), advanced(false) {
+ : years(0), months(0), days(0), begin(), end(), advanced(false) {
TRACE_CTOR(interval_t, "const string&");
std::istringstream stream(desc);
parse(stream);
@@ -99,82 +137,18 @@ struct interval_t
}
operator bool() const {
- return years > 0 || months > 0 || days > 0;
+ return years != 0 || months != 0 || days != 0;
}
void start(const date_t& moment) {
begin = first(moment);
}
- date_t first(const date_t& moment = date_t()) const;
+ date_t first(const optional<date_t>& moment = none) const;
date_t increment(const date_t&) const;
void parse(std::istream& in);
};
-#if 0
-inline datetime_t ptime_local_to_utc(const datetime_t& when) {
- struct std::tm tm_gmt = to_tm(when);
- return boost::posix_time::from_time_t(std::mktime(&tm_gmt));
-}
-
-// jww (2007-04-18): I need to make a general parsing function
-// instead, and then make these into private methods.
-inline datetime_t ptime_from_local_date_string(const string& date_string) {
- return ptime_local_to_utc(datetime_t(boost::gregorian::from_string(date_string),
- time_duration()));
-}
-
-inline datetime_t ptime_from_local_time_string(const string& time_string) {
- return ptime_local_to_utc(boost::posix_time::time_from_string(time_string));
-}
-#endif
-
-inline datetime_t parse_datetime(const string& str) {
- return parse_datetime(str.c_str());
-}
-datetime_t parse_datetime(const char * str);
-
-inline date_t parse_date(const string& str) {
- return gregorian::from_string(str);
-}
-
-inline std::time_t to_time_t(const ptime& t)
-{
- if( t == posix_time::neg_infin )
- return 0;
- else if( t == posix_time::pos_infin )
- return LONG_MAX;
- ptime start(date(1970,1,1));
- return (t-start).total_seconds();
-}
-
-inline string format_datetime(const datetime_t& when) {
- char buf[64];
- time_t moment = to_time_t(when);
- // jww (2008-07-29): Need to make the output format configurable
- std::strftime(buf, 63, "%Y/%m/%d", std::localtime(&moment));
- return buf;
-}
-
-inline string format_date(const date_t& when) {
- return to_iso_extended_string(when);
-}
-
-#if 0
-struct intorchar
-{
- int ival;
- string sval;
-
- intorchar() : ival(-1) {}
- intorchar(int val) : ival(val) {}
- intorchar(const string& val) : ival(-1), sval(val) {}
- intorchar(const intorchar& o) : ival(o.ival), sval(o.sval) {}
-};
-
-ledger::datetime_t parse_abs_datetime(std::istream& input);
-#endif
-
} // namespace ledger
#endif // _TIMES_H
diff --git a/walk.cc b/walk.cc
index 20fde04d..4d45dab3 100644
--- a/walk.cc
+++ b/walk.cc
@@ -438,15 +438,10 @@ void subtotal_xacts::report_subtotal(const char * spec_fmt)
std::ostringstream out_date;
if (! spec_fmt) {
string fmt = "- ";
- fmt += output_time_format; // jww (2008-04-24): output_date_format?
- // jww (2008-04-24): There is no date output function?
-#if 0
- finish.write(out_date, fmt);
-#endif
+ fmt += output_date_format;
+ out_date << format_date(finish, string(fmt));
} else {
-#if 0
- finish.write(out_date, spec_fmt);
-#endif
+ out_date << format_date(finish, string(spec_fmt));
}
entry_temps.push_back(entry_t());
diff --git a/walk.h b/walk.h
index fe08918b..9024a589 100644
--- a/walk.h
+++ b/walk.h
@@ -657,8 +657,8 @@ protected:
values_map values;
bool remember_components;
- std::list<entry_t> entry_temps;
- std::list<xact_t> xact_temps;
+ std::list<entry_t> entry_temps;
+ std::list<xact_t> xact_temps;
public:
date_t start;