-
Notifications
You must be signed in to change notification settings - Fork 0
/
ms_money_parser.rb
89 lines (68 loc) · 2.12 KB
/
ms_money_parser.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
require "csv"
module MsMoney
class Data
attr_reader :file_path, :meta_data, :transactions
def initialize(file_path, meta_data, transactions)
@file_path = file_path
@meta_data = meta_data
@transactions = transactions
end
end
class SimpleCsvDumper
def self.dump(file_path, data)
CSV.open(file_path, "wb") do |csv|
data.meta_data.each do |label, value|
csv << [label, value]
end
csv << []
data.transactions.each do |row|
csv << [row["DTPOSTED"].strftime("%Y-%m-%d %H:%M:%S"), row["MEMO"], row["NAME"], row["TRNAMT"]]
end
end
end
end
class Parser
class << self
def parse(file_path)
# parse meta data
meta_data = parse_meta_data(file_path)
# parse transactions log
all_trx = File.read(file_path).scan(/<STMTTRN>(?:.|\n)*?<\/STMTTRN>/)
transactions = all_trx.map{|trx| parse_trx(trx) }
return MsMoney::Data.new(file_path, meta_data, transactions)
end
private
def parse_meta_data(file_path)
ret = {}
File.foreach(file_path) do |line|
break if line == "\n"
label, value = line.chomp.split(":")
ret[label] = value
end
return ret
end
def parse_trx(trx_line)
ret = {}
trx_line.chomp.gsub(/<\/?STMTTRN>/, "").scan(/<([^>]+)>(.*)\n/).each do |ary|
label, value = ary
value = value.to_i if value =~ /\A-?\d+\z/
value = value.to_f if value =~ /\A-?\d+\.\d+\z/
ret[label] = value
end
ret["DTPOSTED"] = parse_datetime(ret["DTPOSTED"])
return ret
end
def parse_datetime(datetime)
if datetime =~ /(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)\[([\+\-]?\d+(?:\.\d+)?)\:[a-zA-Z]+\]/ then
# TODO: consider timezone?
y, m, d = $1.to_i, $2.to_i, $3.to_i
hour, min, sec = $4.to_i, $5.to_i, $6.to_i
time_zone_diff = $7.to_i
return Time.local(y, m, d, hour, min, sec)
else
return datetime
end
end
end
end
end