summaryrefslogtreecommitdiff
path: root/src/times.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/times.h')
-rw-r--r--src/times.h500
1 files changed, 228 insertions, 272 deletions
diff --git a/src/times.h b/src/times.h
index 94ae4752..d378dd81 100644
--- a/src/times.h
+++ b/src/times.h
@@ -146,12 +146,18 @@ struct date_traits_t
date_traits_t(bool _has_year = false,
bool _has_month = false,
bool _has_day = false)
- : has_year(_has_year), has_month(_has_month), has_day(_has_day) {}
-
+ : has_year(_has_year), has_month(_has_month), has_day(_has_day) {
+ TRACE_CTOR(date_traits_t, "bool, bool, bool");
+ }
date_traits_t(const date_traits_t& traits)
: has_year(traits.has_year),
has_month(traits.has_month),
- has_day(traits.has_day) {}
+ has_day(traits.has_day) {
+ TRACE_CTOR(date_traits_t, "copy");
+ }
+ ~date_traits_t() throw() {
+ TRACE_DTOR(date_traits_t);
+ }
date_traits_t& operator=(const date_traits_t& traits) {
has_year = traits.has_year;
@@ -181,6 +187,100 @@ private:
#endif // HAVE_BOOST_SERIALIZATION
};
+struct date_duration_t
+{
+ enum skip_quantum_t {
+ DAYS, WEEKS, MONTHS, QUARTERS, YEARS
+ } quantum;
+ int length;
+
+ date_duration_t() : quantum(DAYS), length(0) {
+ TRACE_CTOR(date_duration_t, "");
+ }
+ date_duration_t(skip_quantum_t _quantum, int _length)
+ : quantum(_quantum), length(_length) {
+ TRACE_CTOR(date_duration_t, "skip_quantum_t, int");
+ }
+ date_duration_t(const date_duration_t& dur)
+ : quantum(dur.quantum), length(dur.length) {
+ TRACE_CTOR(date_duration_t, "copy");
+ }
+ ~date_duration_t() throw() {
+ TRACE_DTOR(date_duration_t);
+ }
+
+ date_t add(const date_t& date) const {
+ switch (quantum) {
+ case DAYS:
+ return date + gregorian::days(length);
+ case WEEKS:
+ return date + gregorian::weeks(length);
+ case MONTHS:
+ return date + gregorian::months(length);
+ case QUARTERS:
+ return date + gregorian::months(length * 3);
+ case YEARS:
+ return date + gregorian::years(length);
+ default:
+ assert(false); return date_t();
+ }
+ }
+
+ date_t subtract(const date_t& date) const {
+ switch (quantum) {
+ case DAYS:
+ return date - gregorian::days(length);
+ case WEEKS:
+ return date - gregorian::weeks(length);
+ case MONTHS:
+ return date - gregorian::months(length);
+ case QUARTERS:
+ return date - gregorian::months(length * 3);
+ case YEARS:
+ return date - gregorian::years(length);
+ default:
+ assert(false); return date_t();
+ }
+ }
+
+ string to_string() const {
+ std::ostringstream out;
+
+ out << length << ' ';
+
+ switch (quantum) {
+ case DAYS: out << "day"; break;
+ case WEEKS: out << "week"; break;
+ case MONTHS: out << "month"; break;
+ case QUARTERS: out << "quarter"; break;
+ case YEARS: out << "year"; break;
+ default:
+ assert(false);
+ break;
+ }
+
+ if (length > 1)
+ out << 's';
+
+ return out.str();
+ }
+
+ static date_t find_nearest(const date_t& date, skip_quantum_t skip);
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & quantum;
+ ar & length;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
class date_specifier_t
{
friend class date_parser_t;
@@ -200,15 +300,32 @@ class date_specifier_t
optional<day_of_week_type> wday;
public:
- date_specifier_t() {}
- date_specifier_t(const date_t& date, const date_traits_t& traits) {
- if (traits.has_year)
+ date_specifier_t(const optional<year_type>& _year = none,
+ const optional<month_type>& _month = none,
+ const optional<day_type>& _day = none,
+ const optional<day_of_week_type>& _wday = none)
+ : year(_year), month(_month), day(_day), wday(_wday) {
+ TRACE_CTOR(date_specifier_t,
+ "year_type, month_type, day_type, day_of_week_type");
+ }
+ date_specifier_t(const date_t& date,
+ const optional<date_traits_t>& traits = none) {
+ TRACE_CTOR(date_specifier_t, "date_t, date_traits_t");
+ if (! traits || traits->has_year)
year = date.year();
- if (traits.has_month)
+ if (! traits || traits->has_month)
month = date.month();
- if (traits.has_day)
+ if (! traits || traits->has_day)
day = date.day();
}
+ date_specifier_t(const date_specifier_t& other)
+ : year(other.year), month(other.month),
+ day(other.day), wday(other.wday) {
+ TRACE_CTOR(date_specifier_t, "copy");
+ }
+ ~date_specifier_t() throw() {
+ TRACE_DTOR(date_specifier_t);
+ }
date_t begin(const optional_year& current_year = none) const;
date_t end(const optional_year& current_year = none) const;
@@ -218,6 +335,32 @@ public:
return date >= begin(current_year) && date < end(current_year);
}
+ optional<date_duration_t> implied_duration() const {
+ if (day || wday)
+ return date_duration_t(date_duration_t::DAYS, 1);
+ else if (month)
+ return date_duration_t(date_duration_t::MONTHS, 1);
+ else if (year)
+ return date_duration_t(date_duration_t::YEARS, 1);
+ else
+ return none;
+ }
+
+ string to_string() const {
+ std::ostringstream out;
+
+ if (year)
+ out << " year " << *year;
+ if (month)
+ out << " month " << *month;
+ if (day)
+ out << " day " << *day;
+ if (wday)
+ out << " wday " << *wday;
+
+ return out.str();
+ }
+
#if defined(HAVE_BOOST_SERIALIZATION)
private:
/** Serialization. */
@@ -241,7 +384,24 @@ class date_range_t
optional<date_specifier_t> range_begin;
optional<date_specifier_t> range_end;
+ bool end_inclusive;
+
public:
+ date_range_t(const optional<date_specifier_t>& _range_begin = none,
+ const optional<date_specifier_t>& _range_end = none)
+ : range_begin(_range_begin), range_end(_range_end),
+ end_inclusive(false) {
+ TRACE_CTOR(date_range_t, "date_specifier_t, date_specifier_t");
+ }
+ date_range_t(const date_range_t& other)
+ : range_begin(other.range_begin), range_end(other.range_end),
+ end_inclusive(other.end_inclusive) {
+ TRACE_CTOR(date_range_t, "date_range_t");
+ }
+ ~date_range_t() throw() {
+ TRACE_DTOR(date_range_t);
+ }
+
optional<date_t> begin(const optional_year& current_year = none) const {
if (range_begin)
return range_begin->begin(current_year);
@@ -249,10 +409,14 @@ public:
return none;
}
optional<date_t> end(const optional_year& current_year = none) const {
- if (range_end)
- return range_end->end(current_year);
- else
+ if (range_end) {
+ if (end_inclusive)
+ return range_end->end(current_year);
+ else
+ return range_end->begin(current_year);
+ } else {
return none;
+ }
}
bool is_within(const date_t& date,
@@ -264,70 +428,15 @@ public:
return after_begin && before_end;
}
-#if defined(HAVE_BOOST_SERIALIZATION)
-private:
- /** Serialization. */
-
- friend class boost::serialization::access;
-
- template<class Archive>
- void serialize(Archive& ar, const unsigned int /* version */) {
- ar & range_begin;
- ar & range_end;
- }
-#endif // HAVE_BOOST_SERIALIZATION
-};
-
-struct date_duration_t
-{
- enum skip_quantum_t {
- DAYS, WEEKS, MONTHS, YEARS
- } quantum;
- int length;
+ string to_string() const {
+ std::ostringstream out;
- date_duration_t() : quantum(DAYS), length(0) {
- TRACE_CTOR(date_duration_t, "");
- }
- date_duration_t(skip_quantum_t _quantum, int _length)
- : quantum(_quantum), length(_length) {
- TRACE_CTOR(date_duration_t, "skip_quantum_t, int");
- }
- date_duration_t(const date_duration_t& dur)
- : quantum(dur.quantum), length(dur.length) {
- TRACE_CTOR(date_duration_t, "copy");
- }
- ~date_duration_t() throw() {
- TRACE_DTOR(date_duration_t);
- }
-
- date_t add(const date_t& date) const {
- switch (quantum) {
- case DAYS:
- return date + gregorian::days(length);
- case WEEKS:
- return date + gregorian::weeks(length);
- case MONTHS:
- return date + gregorian::months(length);
- case YEARS:
- return date + gregorian::years(length);
- default:
- assert(false); return date_t();
- }
- }
-
- date_t subtract(const date_t& date) const {
- switch (quantum) {
- case DAYS:
- return date - gregorian::days(length);
- case WEEKS:
- return date - gregorian::weeks(length);
- case MONTHS:
- return date - gregorian::months(length);
- case YEARS:
- return date - gregorian::years(length);
- default:
- assert(false); return date_t();
- }
+ if (range_begin)
+ out << "from" << range_begin->to_string();
+ if (range_end)
+ out << " to" << range_end->to_string();
+
+ return out.str();
}
#if defined(HAVE_BOOST_SERIALIZATION)
@@ -338,8 +447,8 @@ private:
template<class Archive>
void serialize(Archive& ar, const unsigned int /* version */) {
- ar & quantum;
- ar & length;
+ ar & range_begin;
+ ar & range_end;
}
#endif // HAVE_BOOST_SERIALIZATION
};
@@ -351,6 +460,25 @@ class date_specifier_or_range_t
value_type specifier_or_range;
public:
+ date_specifier_or_range_t() {
+ TRACE_CTOR(date_specifier_or_range_t, "");
+ }
+ date_specifier_or_range_t(const date_specifier_or_range_t& other)
+ : specifier_or_range(other.specifier_or_range) {
+ TRACE_CTOR(date_specifier_or_range_t, "copy");
+ }
+ date_specifier_or_range_t(const date_specifier_t& specifier)
+ : specifier_or_range(specifier) {
+ TRACE_CTOR(date_specifier_or_range_t, "date_specifier_t");
+ }
+ date_specifier_or_range_t(const date_range_t& range)
+ : specifier_or_range(range) {
+ TRACE_CTOR(date_specifier_or_range_t, "date_range_t");
+ }
+ ~date_specifier_or_range_t() throw() {
+ TRACE_DTOR(date_specifier_or_range_t);
+ }
+
optional<date_t> begin(const optional_year& current_year = none) const {
if (specifier_or_range.type() == typeid(date_specifier_t))
return boost::get<date_specifier_t>(specifier_or_range).begin(current_year);
@@ -368,6 +496,18 @@ public:
return none;
}
+
+ string to_string() const {
+ std::ostringstream out;
+
+ if (specifier_or_range.type() == typeid(date_specifier_t))
+ out << "in" << boost::get<date_specifier_t>(specifier_or_range).to_string();
+ else if (specifier_or_range.type() == typeid(date_range_t))
+ out << boost::get<date_range_t>(specifier_or_range).to_string();
+
+ return out.str();
+ }
+
#if defined(HAVE_BOOST_SERIALIZATION)
private:
/** Serialization. */
@@ -439,17 +579,12 @@ public:
return finish ? finish : (range ? range->end(current_year) : none);
}
- void parse(std::istream& in);
-
- void parse(const string& str) {
- std::istringstream in(str);
- parse(in);
- }
+ void parse(const string& str);
- void resolve_end();
- void stabilize(const optional<date_t>& date = none);
+ void resolve_end();
+ void stabilize(const optional<date_t>& date = none);
- bool is_valid() const {
+ bool is_valid() const {
return start;
}
@@ -458,6 +593,12 @@ public:
containing date, or false if no such period can be found. */
bool find_period(const date_t& date);
+ optional<date_t> inclusive_skip_end() const {
+ if (skip_duration)
+ return skip_duration->add(*start) - gregorian::days(1);
+ else
+ return none;
+ }
optional<date_t> inclusive_end() const {
if (end_of_duration)
return *end_of_duration - gregorian::days(1);
@@ -467,6 +608,8 @@ public:
date_interval_t& operator++();
+ void dump(std::ostream& out);
+
#if defined(HAVE_BOOST_SERIALIZATION)
private:
/** Serialization. */
@@ -488,197 +631,10 @@ private:
#endif // HAVE_BOOST_SERIALIZATION
};
-class date_parser_t
-{
- friend void show_period_tokens(std::ostream& out, const string& arg);
-
- class lexer_t
- {
- friend class date_parser_t;
-
- string::const_iterator begin;
- string::const_iterator end;
-
- public:
- struct token_t
- {
- enum kind_t {
- UNKNOWN,
-
- TOK_DATE,
- TOK_INT,
- TOK_SLASH,
- TOK_DASH,
- TOK_DOT,
-
- TOK_A_YEAR,
- TOK_A_MONTH,
- TOK_A_DAY,
- TOK_A_WDAY,
-
- TOK_SINCE,
- TOK_UNTIL,
- TOK_IN,
- TOK_THIS,
- TOK_NEXT,
- TOK_LAST,
-
- TOK_YEAR,
- TOK_QUARTER,
- TOK_MONTH,
- TOK_WEEK,
- TOK_DAY,
-
- TOK_YEARLY,
- TOK_QUARTERLY,
- TOK_BIMONTHLY,
- TOK_MONTHLY,
- TOK_BIWEEKLY,
- TOK_WEEKLY,
- TOK_DAILY,
-
- TOK_YEARS,
- TOK_QUARTERS,
- TOK_MONTHS,
- TOK_WEEKS,
- TOK_DAYS,
-
- END_REACHED
-
- } kind;
-
- typedef variant<string, int, date_specifier_t> content_t;
-
- optional<content_t> value;
-
- explicit token_t(kind_t _kind = UNKNOWN,
- const optional<content_t>& _value = none)
- : kind(_kind), value(_value) {
- TRACE_CTOR(date_parser_t::lexer_t::token_t, "");
- }
- token_t(const token_t& tok)
- : kind(tok.kind), value(tok.value) {
- TRACE_CTOR(date_parser_t::lexer_t::token_t, "copy");
- }
- ~token_t() throw() {
- TRACE_DTOR(date_parser_t::lexer_t::token_t);
- }
-
- token_t& operator=(const token_t& tok) {
- if (this != &tok) {
- kind = tok.kind;
- value = tok.value;
- }
- return *this;
- }
-
- operator bool() const {
- return kind != END_REACHED;
- }
-
- string to_string() const {
- switch (kind) {
- case UNKNOWN: return "UNKNOWN";
- case TOK_DATE: return "TOK_DATE";
- case TOK_INT: return "TOK_INT";
- case TOK_SLASH: return "TOK_SLASH";
- case TOK_DASH: return "TOK_DASH";
- case TOK_DOT: return "TOK_DOT";
- case TOK_A_YEAR: return "TOK_A_YEAR";
- case TOK_A_MONTH: return "TOK_A_MONTH";
- case TOK_A_DAY: return "TOK_A_DAY";
- case TOK_A_WDAY: return "TOK_A_WDAY";
- case TOK_SINCE: return "TOK_SINCE";
- case TOK_UNTIL: return "TOK_UNTIL";
- case TOK_IN: return "TOK_IN";
- case TOK_THIS: return "TOK_THIS";
- case TOK_NEXT: return "TOK_NEXT";
- case TOK_LAST: return "TOK_LAST";
- case TOK_YEAR: return "TOK_YEAR";
- case TOK_QUARTER: return "TOK_QUARTER";
- case TOK_MONTH: return "TOK_MONTH";
- case TOK_WEEK: return "TOK_WEEK";
- case TOK_DAY: return "TOK_DAY";
- case TOK_YEARLY: return "TOK_YEARLY";
- case TOK_QUARTERLY: return "TOK_QUARTERLY";
- case TOK_BIMONTHLY: return "TOK_BIMONTHLY";
- case TOK_MONTHLY: return "TOK_MONTHLY";
- case TOK_BIWEEKLY: return "TOK_BIWEEKLY";
- case TOK_WEEKLY: return "TOK_WEEKLY";
- case TOK_DAILY: return "TOK_DAILY";
- case TOK_YEARS: return "TOK_YEARS";
- case TOK_QUARTERS: return "TOK_QUARTERS";
- case TOK_MONTHS: return "TOK_MONTHS";
- case TOK_WEEKS: return "TOK_WEEKS";
- case TOK_DAYS: return "TOK_DAYS";
- case END_REACHED: return "END_REACHED";
- }
- assert(false);
- return empty_string;
- }
-
- void unexpected();
- static void expected(char wanted, char c = '\0');
- };
-
- token_t token_cache;
-
- lexer_t(string::const_iterator _begin,
- string::const_iterator _end)
- : begin(_begin), end(_end)
- {
- TRACE_CTOR(date_parser_t::lexer_t, "");
- }
- lexer_t(const lexer_t& lexer)
- : begin(lexer.begin), end(lexer.end),
- token_cache(lexer.token_cache)
- {
- TRACE_CTOR(date_parser_t::lexer_t, "copy");
- }
- ~lexer_t() throw() {
- TRACE_DTOR(date_parser_t::lexer_t);
- }
-
- token_t next_token();
- void push_token(token_t tok) {
- assert(token_cache.kind == token_t::UNKNOWN);
- token_cache = tok;
- }
- token_t peek_token() {
- if (token_cache.kind == token_t::UNKNOWN)
- token_cache = next_token();
- return token_cache;
- }
- };
-
- string arg;
- lexer_t lexer;
-
- date_interval_t parse_date_expr();
-
-public:
- date_parser_t(const string& _arg)
- : arg(_arg), lexer(arg.begin(), arg.end()) {
- TRACE_CTOR(date_parser_t, "");
- }
- date_parser_t(const date_parser_t& parser)
- : arg(parser.arg), lexer(parser.lexer) {
- TRACE_CTOR(date_parser_t, "copy");
- }
- ~date_parser_t() throw() {
- TRACE_DTOR(date_parser_t);
- }
-
- date_interval_t parse() {
- return date_interval_t();
- }
-};
-
void times_initialize();
void times_shutdown();
void show_period_tokens(std::ostream& out, const string& arg);
-void analyze_period(std::ostream& out, const string& arg);
std::ostream& operator<<(std::ostream& out, const date_duration_t& duration);