Created
June 3, 2015 18:37
-
-
Save cmaggard/b649418859aa17320f73 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
require 'set' | |
class DateGuesser | |
class DateGuesserError < StandardError; end | |
class UnguessableYearError < DateGuesserError; end | |
class UnguessableDayError < DateGuesserError; end | |
def guess(d) | |
begin | |
guess_year_position d unless @ypos | |
guess_day_position d | |
guess_month_position d | |
build_strftime_string d | |
rescue | |
@delim = nil | |
return nil | |
end | |
end | |
def determine_delimiter(d) | |
@delim ||= d.match(/[\/\\-]/)[0] | |
end | |
def guess_year_position(d) | |
@ypos ||= begin | |
delim = determine_delimiter(d) | |
idx = d.split(delim).find_index {|elem| elem.length > 2 or elem.to_i > 31} | |
raise UnguessableYearError if idx.nil? | |
if d.split(delim)[idx].length > 2 | |
[idx, "%Y"] | |
else | |
[idx, "%y"] | |
end | |
end | |
end | |
def guess_day_position(d) | |
@dpos ||= begin | |
year_idx = guess_year_position(d)[0] | |
delim = determine_delimiter(d) | |
idxes = d.split(delim).each_with_index.map{|elem, i| i if elem.to_i > 12}.compact | |
idxes.delete year_idx | |
raise UnguessableDayError unless idxes.length == 1 | |
[idxes.first, "%d"] | |
end | |
end | |
def guess_month_position(d) | |
@mpos ||= begin | |
year_idx = guess_year_position(d)[0] | |
day_idx = guess_day_position(d)[0] | |
[(Set.new(0..2) - Set.new([year_idx, day_idx])).first, '%m'] | |
end | |
end | |
def build_strftime_string(d) | |
return [@ypos, @mpos, @dpos].sort_by{|x| x[0]}.map{|x| x[1]}.join(@delim) | |
end | |
end |
This file contains hidden or 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
require_relative '../../lib/date_guesser' | |
describe DateGuesser do | |
subject { DateGuesser.new } | |
it 'should take in a date string' do | |
expect { | |
subject.parse | |
}.to raise_error | |
end | |
it 'should guess the "/" delimiter' do | |
subject.determine_delimiter('2014/12/31').should eq('/') | |
end | |
it 'should guess the "\\" delimiter' do | |
subject.determine_delimiter('2014\\12\\31').should eq('\\') | |
end | |
it 'should guess the "-" delimiter' do | |
subject.determine_delimiter('2014-12-31').should eq('-') | |
end | |
it 'should guess the year position' do | |
subject.guess_year_position('2014/12/31').should eq([0, '%Y']) | |
end | |
it 'should handle two digit years if it can guess them' do | |
subject.guess_year_position('87/12/31').should eq([0, '%y']) | |
end | |
it "should return nil if it can't guess the year position (ambiguousity)" do | |
expect { | |
subject.guess_year_position('14/12/31').should eq([0, '%Y']) | |
}.to raise_error | |
end | |
it 'should guess the day position' do | |
subject.guess_day_position('2014-12-31').should eq([2, '%d']) | |
end | |
it "should raise an error if it can't guess the day position (ambiguosity)" do | |
expect { | |
subject.guess_day_position('2014-12-11').should eq([2, '%d']) | |
}.to raise_error | |
end | |
it 'should guess the month position' do | |
subject.guess_month_position('2014-12-31').should eq([1, '%m']) | |
end | |
it 'should return a strfparse-able string if we know everything' do | |
subject.guess('2014-12-31').should eq '%Y-%m-%d' | |
end | |
it 'should return nil if we need more information' do | |
subject.guess('2014-12-7').should eq(nil) | |
end | |
it 'should build on prior info to build a string as quickly as possible' do | |
subject.guess('2014-12-05').should eq(nil) | |
subject.guess('2014-31-07').should eq('%Y-%d-%m') | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment