Skip to content

Adding support to single-digit formats for date, using other separators also (like single-quote) #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 35 additions & 33 deletions lib/qif/date_format.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,61 @@

module Qif
class DateFormat
attr_reader :format
attr_reader :conversion_format

def initialize(format = 'dd/mm/yyyy')
@format = format
@conversion_format = format
end

def parse(date)
regex = convert_format_to_regex
order = date_order

if match = regex.match(date)
year = match[order.index('y')+1].to_i
if year < 100
start_year = Time.now.year - 50
start_cent = (start_year/100).to_i*100
if year > start_year-start_cent
year += start_cent
else
year += ((Time.now.year/100).to_i*100)
end
end
Time.mktime(year, *%w(m d).map{|t| match[order.index(t) + 1].to_i })
year = match[order.index('y')+1].to_i

if year < 100
start_year = Time.now.year - 50
start_cent = (start_year/100).to_i*100
if year > start_year-start_cent
year += start_cent
else
year += ((Time.now.year/100).to_i*100)
end
end

Time.mktime(year, *%w(m d).map{|t| match[order.index(t) + 1].to_i })
end
end

def format(date)
date.strftime(convert_format_to_strftime)
end

private

def date_order
%w(d m y).sort{|a,b| @format.index(a) <=> @format.index(b) }
%w(d m y).sort{|a,b| @conversion_format.index(a) <=> @conversion_format.index(b) }
end

def convert_format_to_strftime
format = @format.dup
format.gsub!('dd', '%d')
format.gsub!('mm', '%m')
format = @conversion_format.dup
format.gsub!(/d{1,2}/, '%d')
format.gsub!(/m{1,2}/, '%m')
format.gsub!('yyyy', '%Y')
format.gsub!('yy', '%y')
format
end

def convert_format_to_regex
format = @format.dup
format.gsub!('dd', '([0-3][0-9])')
format.gsub!('mm', '([0-1][0-9])')
format.gsub!('yyyy', '([1-2][0-9]{3})')
format.gsub!('yy', '([0-9]{2})')

format = @conversion_format.dup
format.gsub!('dd' , '([0-3][0-9])')
format.gsub!('d' , '([0-3]?[0-9])')
format.gsub!('mm' , '([0-1][0-9])')
format.gsub!('m' , '([0-1]?[0-9])')
format.gsub!('yyyy' , '([1-2][0-9]{3})')
format.gsub!('yy' , '([0-9]{2})')

/#{format}/mi
end
end
Expand Down
19 changes: 19 additions & 0 deletions spec/fixtures/3_records_mdyy.qif
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
!Type:Bank
D1/1'10
T-10.00
LDebit
PDescription
MReference
^
D6/1'10
T-20.00
LDebit
PDescription
MReference
^
D12/29'10
T30.00
LCredit
PDescription
MReference
^
26 changes: 22 additions & 4 deletions spec/lib/date_format_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,33 @@
reader = Qif::DateFormat.new('mm/dd/yy')
time = reader.parse('09/28/10')
time.should == Time.mktime(2010, 9, 28)
time = reader.parse('09/28/94')
time.should == Time.mktime(1994, 9, 28)
time = reader.parse('09/28/94')
time.should == Time.mktime(1994, 9, 28)
end

it 'should work with 2 digit years in dd/mm/yy format' do
reader = Qif::DateFormat.new('dd/mm/yy')
time = reader.parse('28/09/10')
time.should == Time.mktime(2010, 9, 28)
time = reader.parse('28/09/94')
time.should == Time.mktime(1994, 9, 28)
time = reader.parse('28/09/94')
time.should == Time.mktime(1994, 9, 28)
end

it 'should work with 1 digit day in d/mm/yy format' do
reader = Qif::DateFormat.new('d/mm/yy')
time = reader.parse('8/09/10')
time.should == Time.mktime(2010, 9, 8)
end

it 'should work with 1 digit month in dd/m/yy format' do
reader = Qif::DateFormat.new('dd/m/yy')
time = reader.parse('18/9/10')
time.should == Time.mktime(2010, 9, 18)
end

it "should work with separators other than /, like '" do
reader = Qif::DateFormat.new("m/d'yy")
time = reader.parse("9/8'10")
time.should == Time.mktime(2010, 9, 8)
end
end
6 changes: 4 additions & 2 deletions spec/lib/reader_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,11 @@
end

describe Qif::Reader do
%w(dd/mm/yyyy mm/dd/yyyy dd/mm/yy mm/dd/yy).each do |format|
%w(dd/mm/yyyy mm/dd/yyyy dd/mm/yy mm/dd/yy d/m/yy m/d'yy).each do |format|
context "when format is #{format}" do
it_behaves_like "3 record files" do
let(:instance) { Qif::Reader.new(open('spec/fixtures/3_records_%s.qif' % format.gsub('/', '')).read, format) }
file_name = 'spec/fixtures/3_records_%s.qif' % format.gsub('/', '').gsub("'", '')
let(:instance) { Qif::Reader.new(open(file_name).read, format) }
end
end
end
Expand All @@ -58,6 +59,7 @@
it 'should reject the wrong file and raise an UnrecognizedData exception' do
expect{ Qif::Reader.new(open('spec/fixtures/not_a_QIF_file.txt')) }.to raise_error(Qif::Reader::UnrecognizedData)
end

it 'should guess the date format dd/mm/yyyy' do
@instance = Qif::Reader.new(open('spec/fixtures/3_records_ddmmyyyy.qif'))
@instance.guess_date_format.should == 'dd/mm/yyyy'
Expand Down