Created
September 3, 2008 00:42
-
-
Save cwsaylor/8508 to your computer and use it in GitHub Desktop.
Script to generate a csv file of your future income, bills, expenses
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env ruby | |
# Usage: ruby bill_generator.rb data.yml 2008-1-1 2008-12-31 | |
# Params: data file, begin date, end date | |
# begin and end date is in the format yyyy-mm-dd | |
# Sample data.yml file entries | |
# Date format is [yyyy, mm, dd] | |
# | |
# # Paid every two weeks | |
# Income1: | |
# amount: 1000 | |
# start: [2008, 1, 18] | |
# repeat: daily | |
# freq: 14 | |
# | |
# # Paid twice a month on the 15th and the last day | |
# Income2: | |
# amount: 1000 | |
# start: [ [2008, 1, 15], [2008, 1, -1] ] | |
# repeat: monthly | |
# freq: 1 | |
# | |
# # Weekly food expense | |
# Food: | |
# amount: -100 | |
# start: [2008, 1, 6] | |
# repeat: weekly | |
# freq: 1 | |
# | |
# # Quarterly bill | |
# Water: | |
# amount: -100 | |
# start: [2008, 1, 20] | |
# repeat: monthly | |
# freq: 3 | |
# | |
# # Monthly bill | |
# Home: | |
# amount: -1000 | |
# start: [2008, 1, 1] | |
# repeat: monthly | |
# freq: 1 | |
# v0.1 | |
# TODO: Date parser for better dates in the yaml file | |
# TODO: Extract bill class out into separate file | |
# TODO: Use command line params lib | |
require 'yaml' | |
require 'date' | |
class Bill | |
def initialize(name, params) | |
@name = name | |
@amount = params['amount'] | |
@start_dates = params['start'] | |
@repeat = params['repeat'] | |
@freq = params['freq'].to_i | |
end | |
attr_accessor :name, :amount | |
def due?(current_date) | |
due = false | |
if @start_dates[0].is_a? Array | |
@start_dates.each do |start_date| | |
# No need to check others if it matches | |
next if due == true | |
due = check_for_repeat_type(current_date, start_date) | |
end | |
else | |
due = check_for_repeat_type(current_date, @start_dates) | |
end | |
due | |
end | |
private | |
def check_for_repeat_type(current_date, start_date) | |
case @repeat | |
when "daily" | |
compare_daily(current_date, start_date) | |
when "weekly" | |
compare_daily(current_date, start_date, @freq * 7) | |
when "monthly" | |
compare_monthly(current_date, start_date) | |
when "yearly" | |
compare_yearly(current_date, start_date) | |
else | |
raise ArgumentError, "Invalid repeat option. Must be one of daily, weekly, monthly, or yearly" | |
end | |
end | |
def compare_daily(current_date, start_date, freq = @freq) | |
# Custom freq allows us to convert weekly to daily | |
start_date = convert_date(start_date) | |
((current_date - start_date) % freq) == 0 | |
end | |
def compare_monthly(current_date, start_date) | |
# Check for end of month comparison | |
if start_date[2].to_i == -1 | |
start_date = convert_date(start_date) | |
((current_date.month - start_date.month) % @freq == 0) && current_date.day == end_of_month_day(current_date) | |
else | |
start_date = convert_date(start_date) | |
((current_date.month - start_date.month) % @freq == 0) && current_date.day == start_date.day | |
end | |
end | |
def compare_yearly(current_date, start_date) | |
((current_date.year - start_date.year) % @freq == 0) && current_date.month == start_date.month && current_date.day == start_date.day | |
end | |
# Accepts format of [year, month, day] | |
def convert_date(date) | |
Date.new(*date) | |
end | |
def end_of_month_day(current_date) | |
Date.new(current_date.year, current_date.month, -1).day | |
end | |
end | |
# Begin script | |
file = ARGV[0] | |
date_start = Date.parse(ARGV[1].to_s) | |
date_end = Date.parse(ARGV[2].to_s) | |
bills = YAML.load_file(file) | |
(date_start..date_end).each do |date| | |
bills.each do |name, info| | |
bill = Bill.new(name, info) | |
puts "#{bill.name}, #{date.to_s.strip}, #{bill.amount}" if bill.due? date | |
end | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment