Skip to content

Instantly share code, notes, and snippets.

@tamouse
Created December 24, 2012 06:01
Show Gist options
  • Save tamouse/4367947 to your computer and use it in GitHub Desktop.
Save tamouse/4367947 to your computer and use it in GitHub Desktop.
Simple ruby script to parse checking account history CSV file and print a summary of aggregated transactions
#!/usr/bin/env ruby
=begin
spending.rb -- show how I'm spending my money
usage:
spending.rb history.csv
=end
require 'csv'
=begin
convert_time
*param:*:: timestring - string containing the time to convert
*return:*:: Time object constructed from the elements in the timestring
In the input file, the transaction date has the form:
"m/d/y h:m:s am"
How US-centric. None of the standard Time, DateTime or Date parsing functions
deal with this crazy US format. Luckily, scan easily extracts the necessary
numeric bits, and a match will extract the AM/PM part.
=end
def convert_time(timestring)
timeparts = timestring.scan(/\d+/)
timeparts.map! {|p| p.to_i} # this replaces all the stringy bits picked up in the scan
# with their integer interpretations.
am_pm = timestring.match(/[AP]M/).to_s # check the trailing AM/PM indicator in the timestring
# and set the matching value to a string. This lets me
# do the comparison in the following instruction
timeparts[3] += 12 if am_pm == "PM"
# getting the local time here instead of GMT/UTC.
# the transaction time might actually be America/Los_Angeles since
# the bank is in California, but close enough for my purposes.
Time.local(timeparts[2],timeparts[0],timeparts[1],timeparts[3],timeparts[4],timeparts[5])
end
=begin
add_to (bucket)
Add the amount to the given bucket's who key.
*param:*:: bucket -- the hash that will contain the key who, which will get amount added to it
*param:*:: who -- key in bucket which gets the additional amount
*param:*:: amount -- dollar amount to add to bucket[key]
*side effect:*:: amount is converted to cents here
What's special here is that as bucket will be initialized to empty in the beginning,
there's no garantee that the who key will be in the hash yet. So you can't do += on a
nil value, I test for it, and if bucket[who] is nil, then just assign amount
rather than adding.
=end
def add_to(bucket,who,amount)
amount = (amount*100).floor
if bucket.has_key?(who)
bucket[who] += amount
else
bucket[who] = amount
end
end
=begin
print_summary -- does the nice formatting for the bucket
*param:*:: bucket -- hash to print out
=end
def print_summary(bucket)
bucket.keys.sort.each do |t|
puts "%-70s:\t %5d\n" % [ t, bucket[t]/100 ]
end
end
=begin
Will work on the first account history csv file only.
TODO: work with more files?
=end
if ARGV.empty?
errmsg = "ERROR: Missing history.csv file\nUsage: spending.rb history.csv"
STDERR.puts errmsg
raise errmsg
end
statement = CSV.table(ARGV.first)
spending = {}
deposits = {}
beginning = ending = convert_time(statement.first[:transaction_date])
statement.each do |t|
transaction_time = convert_time(t[:transaction_date])
beginning = transaction_time if transaction_time < beginning
ending = transaction_time if transaction_time > ending
who = t[:extdesc].empty? ? t[:description] : t[:extdesc]
if t[:amount] < 0
add_to(spending,who,t[:amount].abs)
else
add_to(deposits,who,t[:amount])
end
end
report_title = "Period beginning #{beginning.to_s} and ending #{ending.to_s}"
puts report_title
puts "=" * report_title.length
puts
puts "Deposits:"
puts "-" * "Deposits:".length
print_summary(deposits)
puts
puts "Spending:"
puts "-" * "Spending:".length
print_summary(spending)
puts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment