Skip to content

Commit

Permalink
Make date more type-safe
Browse files Browse the repository at this point in the history
  • Loading branch information
wichtounet committed Oct 5, 2023
1 parent 81b8384 commit eb2f9e6
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 64 deletions.
24 changes: 21 additions & 3 deletions include/date.hpp
Expand Up @@ -67,6 +67,14 @@ struct month {
return *this;
}

month operator-(date_type remove) const {
return {static_cast<date_type>(value - remove)};
}

month operator+(date_type add) const {
return {static_cast<date_type>(value + add)};
}

std::string as_short_string() const {
static constexpr const std::array months{"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
Expand All @@ -86,13 +94,19 @@ struct month {
}

bool is_valid() const {
return value <= 13;
return value < 13;
}

bool is_last() const {
return value == 12;
}

month operator++() {
++value;
return *this;
}

friend auto operator<=>(const month & lhs, const month & rhs) = default;
};

struct year {
Expand Down Expand Up @@ -122,6 +136,8 @@ struct year {
++value;
return *this;
}

friend auto operator<=>(const year & lhs, const year & rhs) = default;
};

struct days {
Expand Down Expand Up @@ -174,6 +190,8 @@ struct date {
}
}

// TODO date(year y, month m, day d) : date(y.value, m.value, d.value) {}

budget::year year() const {
return budget::year{_year};
}
Expand Down Expand Up @@ -494,8 +512,8 @@ inline std::string to_string(budget::date date){

struct data_cache;

unsigned short start_year(data_cache & cache);
unsigned short start_month(data_cache & cache, budget::year year);
budget::year start_year(data_cache & cache);
budget::month start_month(data_cache & cache, budget::year year);

} //end of namespace budget

Expand Down
6 changes: 3 additions & 3 deletions src/compute.cpp
Expand Up @@ -21,7 +21,7 @@ budget::status budget::compute_year_status(data_cache & cache) {
}

budget::status budget::compute_year_status(data_cache & cache, year year) {
return compute_year_status(cache, year, 12);
return compute_year_status(cache, year, month(12));
}

budget::status budget::compute_year_status(data_cache & cache, year year, month month) {
Expand All @@ -32,7 +32,7 @@ budget::status budget::compute_year_status(data_cache & cache, year year, month
status.expenses = fold_left_auto(all_expenses_between(cache, year, sm, month) | to_amount);
status.earnings = fold_left_auto(all_earnings_between(cache, year, sm, month) | to_amount);

for (unsigned short i = sm; i <= month; ++i) {
for (budget::month i = sm; i <= month; ++i) {
status.budget += fold_left_auto(all_accounts(cache, year, i) | to_amount);
status.base_income += get_base_income(cache, budget::date(year, i, 1));
}
Expand Down Expand Up @@ -97,7 +97,7 @@ budget::status budget::compute_avg_month_status(data_cache & cache, month month)
budget::status budget::compute_avg_month_status(data_cache & cache, year year, month month) {
budget::status avg_status;

for (budget::month m = 1; m < month; m = m + 1) {
for (budget::month m(1); m < month; ++m) {
auto status = compute_month_status(cache, year, m);

avg_status.expenses += status.expenses;
Expand Down
6 changes: 3 additions & 3 deletions src/date.cpp
Expand Up @@ -62,7 +62,7 @@ std::string budget::date_to_string(const budget::date& date) {
}

// Convert the month
auto* month_ptr = date.month() < 10 ? str.data() + 6 : str.data() + 5;
auto* month_ptr = date.month() < budget::month(10) ? str.data() + 6 : str.data() + 5;
if (auto [p, ec] = std::to_chars(month_ptr, str.data() + 7, static_cast<date_type>(date.month())); ec != std::errc() || p != str.data() + 7) {
throw date_exception("Can't convert month to string");
}
Expand All @@ -76,12 +76,12 @@ std::string budget::date_to_string(const budget::date& date) {
return str;
}

unsigned short budget::start_month(data_cache & cache, budget::year year){
budget::month budget::start_month(data_cache & cache, budget::year year){
const budget::month m = min_with_default(cache.expenses() | filter_by_year(year) | to_month, 12);
return min_with_default(cache.earnings() | filter_by_year(year) | to_month, m);
}

unsigned short budget::start_year(data_cache & cache){
budget::year budget::start_year(data_cache & cache){
auto today = budget::local_day();
const budget::year y = min_with_default(cache.expenses() | not_template | to_year, today.year());
return min_with_default(cache.earnings() | not_template | to_year, y);
Expand Down
4 changes: 1 addition & 3 deletions src/objectives.cpp
Expand Up @@ -111,9 +111,7 @@ void budget::monthly_objective_status(budget::writer& w){
std::vector<std::string> columns = {objective.name, "Status", "Progress"};
std::vector<std::vector<std::string>> contents;

for (unsigned short i = sm; i <= current_month; ++i) {
budget::month const month = i;

for (budget::month month = sm; month <= current_month; ++month) {
// Compute the month status
auto status = budget::compute_month_status(w.cache, current_year, month);

Expand Down
48 changes: 18 additions & 30 deletions src/overview.cpp
Expand Up @@ -36,14 +36,10 @@ bool invalid_accounts_all(){

const std::vector<budget::account> previous = all_accounts(cache, sy, start_month(cache, sy));

for(unsigned short j = sy; j <= today.year(); ++j){
const budget::year year = j;

for(budget::year year = sy; year <= today.year(); ++year){
auto sm = start_month(cache, year);

for(unsigned short i = sm; i < 13; ++i){
const budget::month month = i;

for(budget::month month = sm; month.is_valid(); ++month){
auto current_accounts = all_accounts(cache, year, month);

if(current_accounts.size() != previous.size()){
Expand Down Expand Up @@ -77,10 +73,8 @@ bool invalid_accounts(budget::year year){

std::vector<budget::account> previous = all_accounts(cache, year, sm);

for(unsigned short i = sm + 1; i < 13; ++i){
const budget::month month = i;

auto current_accounts = all_accounts(cache, year, month);
for(budget::month m = sm + date_type(1); m.is_valid(); ++m){
auto current_accounts = all_accounts(cache, year, m);

if(current_accounts.size() != previous.size()){
return true;
Expand Down Expand Up @@ -163,11 +157,11 @@ budget::money compute_total_budget_account(budget::account & account, budget::mo
}
}

if (y != year && m == 12) {
if (y != year && m.is_last()) {
break;
}

m = m + 1;
++m;
}
}

Expand Down Expand Up @@ -209,7 +203,7 @@ std::vector<budget::money> compute_total_budget(data_cache & cache, budget::mont
tmp[account.name] += fold_left_auto(all_earnings_month(cache, account.id, y, m) | to_amount);
}

if(y != year && m == 12){
if(y != year && m.is_last()){
break;
}

Expand Down Expand Up @@ -505,16 +499,16 @@ void add_month_columns(std::vector<std::string>& columns, budget::month sm){
}
}

int get_current_months(budget::year year){
budget::month get_current_months(budget::year year){
data_cache cache;

auto sm = start_month(cache, year);
auto current_months = 12 - sm + 1;
budget::month current_months = budget::month(12) - sm + budget::month(1);

auto today = budget::local_day();

if(today.year() == year){
current_months = today.month() - sm + 1;
current_months = today.month() - sm + date_type(1);
}

return current_months;
Expand Down Expand Up @@ -589,9 +583,7 @@ void display_values(budget::writer& w, budget::year year, const std::string& tit

//Fill the table

for(unsigned short j = sm; j < 13; ++j){
const budget::month m = j;

for(budget::month m = sm; m.is_valid(); ++m){
for(auto& account : all_accounts(w.cache, year, m)){
budget::money month_total;

Expand All @@ -610,7 +602,7 @@ void display_values(budget::writer& w, budget::year year, const std::string& tit
contents[row_mapping[account.name]].push_back(to_string(month_total));

account_totals[account.name] += month_total;
totals[j-1] += month_total;
totals[m.value - 1] += month_total;

if(m < sm + current_months){
account_current_totals[account.name] += month_total;
Expand Down Expand Up @@ -944,9 +936,7 @@ void budget::display_local_balance(budget::writer& w, budget::year year, bool cu
double total_savings_rate = 0.0;
double current_total_savings_rate = 0.0;

for (unsigned short i = sm; i < 13; ++i) {
const budget::month m = i;

for (budget::month m = sm; m.is_valid(); ++m) {
auto status = compute_month_status(w.cache, year, m);

auto savings = status.income - status.expenses;
Expand All @@ -958,7 +948,7 @@ void budget::display_local_balance(budget::writer& w, budget::year year, bool cu

contents.back().push_back(to_string_precision(savings_rate, 2) + "%");

if (i < sm + current_months) {
if (m < sm + current_months) {
current_total_savings_rate += savings_rate;
}

Expand All @@ -980,9 +970,7 @@ void budget::display_local_balance(budget::writer& w, budget::year year, bool cu
double total_savings_rate = 0.0;
double current_total_savings_rate = 0.0;

for (unsigned short i = sm; i < 13; ++i) {
budget::month const m = i;

for (budget::month m = sm; m.is_valid(); ++m) {
auto status = compute_month_status(w.cache, year - date_type(1), m);

double savings_rate = 0.0;
Expand All @@ -993,7 +981,7 @@ void budget::display_local_balance(budget::writer& w, budget::year year, bool cu

contents.back().push_back(to_string_precision(savings_rate, 2) + "%");

if (i < sm + current_months) {
if (m < sm + current_months) {
current_total_savings_rate += savings_rate;
}

Expand Down Expand Up @@ -1040,7 +1028,7 @@ void budget::display_balance(budget::writer& w, budget::year year, bool relaxed,
auto pretotal = compute_total_budget(w.cache, sm, year);
size_t i = 0;
for(const auto& account : all_accounts(w.cache, year, sm)){
account_previous[account.name][sm - 1] += pretotal[i++] - account.amount;
account_previous[account.name][sm.value - 1] += pretotal[i++] - account.amount;
}
}

Expand Down Expand Up @@ -1343,7 +1331,7 @@ void budget::display_year_overview(budget::year year, budget::writer& w){
}

auto today = budget::local_day();
const bool current = year == today.year() && today.month() != 12;
const bool current = year == today.year() && today.month() != budget::month(12);

display_local_balance(w, year, current, false, true);
display_balance(w, year, false, true);
Expand Down
4 changes: 2 additions & 2 deletions src/predict.cpp
Expand Up @@ -65,9 +65,9 @@ void predict_overview(){
}
}

if (today.month() < 12) {
if (today.month() < budget::month(12)) {
budget::year prev_year = today.year() - date_type(1);
for (budget::month m = today.month() + 1; m <= 12; m = m + 1) {
for (budget::month m = today.month() + date_type(1); m.is_valid(); ++m) {
for (auto& expense : expenses | filter_by_date(prev_year, m)) {
expense.date = {today.year(), expense.date.month(), expense.date.day()};
}
Expand Down
2 changes: 1 addition & 1 deletion src/recurring.cpp
Expand Up @@ -56,7 +56,7 @@ budget::date last_date(const budget::recurring& recurring) {
}

bool recurring_not_triggered(const budget::recurring & recurring ) {
return last_date(recurring).year() == 1400;
return last_date(recurring).year() == budget::year(1400);
}

void generate_recurring(const budget::date & date, const recurring & recurring) {
Expand Down
24 changes: 11 additions & 13 deletions src/report.cpp
Expand Up @@ -165,9 +165,9 @@ void budget::report(budget::writer& w, budget::year year, bool filter, const std
total_balance = get_base_income(w.cache, budget::date(year, month, 1)) + total_earnings - total_expenses;
}

expenses[month - 1] = total_expenses.dollars();
earnings[month - 1] = total_earnings.dollars();
balances[month - 1] = total_balance.dollars();
expenses[month.value - 1] = total_expenses.dollars();
earnings[month.value - 1] = total_earnings.dollars();
balances[month.value - 1] = total_balance.dollars();

max_expenses = std::max(max_expenses, total_expenses);
max_earnings = std::max(max_earnings, total_earnings);
Expand Down Expand Up @@ -257,39 +257,37 @@ void budget::report(budget::writer& w, budget::year year, bool filter, const std

const auto first_bar = scale_width + 2;

for (auto i = sm; i <= today.month(); ++i) {
const budget::month month = i;

auto col_start = first_bar + (3 * col_width + 4) * (i - sm);
for (budget::month month = sm; month <= today.month(); ++month) {
auto col_start = first_bar + (3 * col_width + 4) * (month.value - sm.value);

//Display month legend
auto month_str = month.as_short_string();
write(graph, 1, col_start + 2, month_str);

for (size_t j = 0; j < expenses[month - 1] / precision; ++j) {
for (size_t j = 0; j < expenses[month.value - 1] / precision; ++j) {
for (size_t x = 0; x < col_width; ++x) {
graph[zero_index + j][col_start + x] = "\033[1;41m \033[0m";
}
}

col_start += col_width + 1;

for (size_t j = 0; j < earnings[month - 1] / precision; ++j) {
for (size_t j = 0; j < earnings[month.value - 1] / precision; ++j) {
for (size_t x = 0; x < col_width; ++x) {
graph[zero_index + j][col_start + x] = "\033[1;42m \033[0m";
}
}

col_start += col_width + 1;

if (balances[month - 1] >= 0) {
for (size_t j = 0; j < balances[month - 1] / precision; ++j) {
if (balances[month.value - 1] >= 0) {
for (size_t j = 0; j < balances[month.value - 1] / precision; ++j) {
for (size_t x = 0; x < col_width; ++x) {
graph[zero_index + j][col_start + x] = "\033[1;44m \033[0m";
}
}
} else {
for (size_t j = 0; j < std::abs(balances[month - 1]) / precision; ++j) {
for (size_t j = 0; j < std::abs(balances[month.value - 1]) / precision; ++j) {
for (size_t x = 0; x < col_width; ++x) {
graph[zero_index - 1 - j][col_start + x] = "\033[1;44m \033[0m";
}
Expand All @@ -299,7 +297,7 @@ void budget::report(budget::writer& w, budget::year year, bool filter, const std

//Display legend

const int start_legend = first_bar + (3 * col_width + 4) * (today.month() - sm + 1) + 4;
const int start_legend = first_bar + (3 * col_width + 4) * (today.month() - sm + date_type(1)) + 4;

graph[4][start_legend - 2] = "|";
graph[3][start_legend - 2] = "|";
Expand Down

0 comments on commit eb2f9e6

Please sign in to comment.