summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2009-02-21 02:08:49 -0400
committerJohn Wiegley <johnw@newartisans.com>2009-02-21 02:10:02 -0400
commita93111470d54e6345617b51fcc939f306854a524 (patch)
tree8a514e7f3d696ba6134907f7296c370c55a1811e
parent4ff8087815c9d93447ddb1651fa3ec8b82bba9be (diff)
downloadfork-ledger-a93111470d54e6345617b51fcc939f306854a524.tar.gz
fork-ledger-a93111470d54e6345617b51fcc939f306854a524.tar.bz2
fork-ledger-a93111470d54e6345617b51fcc939f306854a524.zip
Greatly improved the way "weeks" are iterated
-rw-r--r--src/derive.cc20
-rw-r--r--src/textual.cc2
-rw-r--r--src/times.cc52
-rw-r--r--src/times.h21
4 files changed, 61 insertions, 34 deletions
diff --git a/src/derive.cc b/src/derive.cc
index ea9e7483..a71dc8bb 100644
--- a/src/derive.cc
+++ b/src/derive.cc
@@ -124,26 +124,6 @@ namespace {
}
};
- short string_to_day_of_week(const std::string& str)
- {
- if (str == "sun")
- return 0;
- else if (str == "mon")
- return 1;
- else if (str == "tue")
- return 2;
- else if (str == "wed")
- return 3;
- else if (str == "thu")
- return 4;
- else if (str == "fri")
- return 5;
- else if (str == "sat")
- return 6;
- assert(false);
- return -1;
- }
-
entry_template_t
args_to_entry_template(value_t::sequence_t::const_iterator begin,
value_t::sequence_t::const_iterator end)
diff --git a/src/textual.cc b/src/textual.cc
index eec3be61..b3fb2f2e 100644
--- a/src/textual.cc
+++ b/src/textual.cc
@@ -512,7 +512,7 @@ void instance_t::nomarket_directive(char * line)
void instance_t::year_directive(char * line)
{
- current_year = std::atoi(skip_ws(line + 1));
+ current_year = lexical_cast<int>(skip_ws(line + 1));
}
void instance_t::option_directive(char * line)
diff --git a/src/times.cc b/src/times.cc
index df760d10..b10d9884 100644
--- a/src/times.cc
+++ b/src/times.cc
@@ -33,6 +33,7 @@
namespace ledger {
+int start_of_week = 0;
optional<std::string> input_date_format;
std::string output_datetime_format = "%Y-%m-%d %H:%M:%S";
std::string output_date_format = "%Y-%m-%d";
@@ -58,9 +59,7 @@ namespace {
"%Y",
NULL
};
-}
-namespace {
bool parse_date_mask(const char * date_str, std::tm& result)
{
if (input_date_format) {
@@ -106,6 +105,27 @@ namespace {
}
}
+int string_to_day_of_week(const std::string& str)
+{
+ if (str == "sun" || str == "sunday" || str == "0")
+ return 0;
+ else if (str == "mon" || str == "monday" || str == "1")
+ return 1;
+ else if (str == "tue" || str == "tuesday" || str == "2")
+ return 2;
+ else if (str == "wed" || str == "wednesday" || str == "3")
+ return 3;
+ else if (str == "thu" || str == "thursday" || str == "4")
+ return 4;
+ else if (str == "fri" || str == "friday" || str == "5")
+ return 5;
+ else if (str == "sat" || str == "saturday" || str == "6")
+ return 6;
+
+ assert(false);
+ return -1;
+}
+
datetime_t parse_datetime(const char * str, int)
{
std::tm when;
@@ -130,7 +150,19 @@ date_t interval_t::first(const optional<date_t>& moment)
// 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.
- begin = date_t(moment->year(), gregorian::Jan, 1);
+ assert(moment);
+
+ if (months > 0 || years > 0) {
+ begin = date_t(moment->year(), gregorian::Jan, 1);
+ } else {
+ begin = date_t(*moment - gregorian::days(400));
+
+ // jww (2009-02-21): Add support for starting a week on any day
+ if (weekly) { // move it to a Sunday
+ while (begin.day_of_week() != start_of_week)
+ begin += gregorian::days(1);
+ }
+ }
}
date_t quant(begin);
@@ -281,12 +313,14 @@ void interval_t::parse(std::istream& in)
if (word == "every") {
read_lower_word(in, word);
if (std::isdigit(word[0])) {
- int quantity = std::atol(word.c_str());
+ int quantity = lexical_cast<int>(word);
read_lower_word(in, word);
if (word == "days")
days = quantity;
- else if (word == "weeks")
+ else if (word == "weeks") {
days = 7 * quantity;
+ weekly = true;
+ }
else if (word == "months")
months = quantity;
else if (word == "quarters")
@@ -296,8 +330,10 @@ void interval_t::parse(std::istream& in)
}
else if (word == "day")
days = 1;
- else if (word == "week")
+ else if (word == "week") {
days = 7;
+ weekly = true;
+ }
else if (word == "month")
months = 1;
else if (word == "quarter")
@@ -307,8 +343,10 @@ void interval_t::parse(std::istream& in)
}
else if (word == "daily")
days = 1;
- else if (word == "weekly")
+ else if (word == "weekly") {
days = 7;
+ weekly = true;
+ }
else if (word == "biweekly")
days = 14;
else if (word == "monthly")
diff --git a/src/times.h b/src/times.h
index 54c1dc80..8e0f72f9 100644
--- a/src/times.h
+++ b/src/times.h
@@ -70,8 +70,11 @@ inline bool is_valid(const date_t& moment) {
#endif
#define CURRENT_DATE() boost::gregorian::day_clock::universal_day()
+extern int start_of_week;
extern optional<std::string> input_date_format;
+int string_to_day_of_week(const std::string& str);
+
datetime_t parse_datetime(const char * str, int current_year = -1);
inline datetime_t parse_datetime(const std::string& str, int current_year = -1) {
@@ -128,26 +131,32 @@ struct interval_t
int years;
int months;
int days;
+ bool weekly;
date_t begin;
date_t end;
- interval_t(int _days = 0, int _months = 0, int _years = 0,
- const date_t& _begin = date_t(),
- const date_t& _end = date_t())
+ interval_t(int _days = 0,
+ int _months = 0,
+ int _years = 0,
+ bool _weekly = false,
+ const date_t& _begin = date_t(),
+ const date_t& _end = date_t())
: years(_years), months(_months), days(_days),
- begin(_begin), end(_end) {
- TRACE_CTOR(interval_t, "int, int, int, const date_t&, const date_t&");
+ weekly(_weekly), begin(_begin), end(_end) {
+ TRACE_CTOR(interval_t,
+ "int, int, int, bool, const date_t&, const date_t&");
}
interval_t(const interval_t& other)
: years(other.years),
months(other.months),
days(other.days),
+ weekly(other.weekly),
begin(other.begin),
end(other.end) {
TRACE_CTOR(interval_t, "copy");
}
interval_t(const string& desc)
- : years(0), months(0), days(0), begin(), end() {
+ : years(0), months(0), days(0), weekly(false), begin(), end() {
TRACE_CTOR(interval_t, "const string&");
std::istringstream stream(desc);
parse(stream);