Skip to content

Instantly share code, notes, and snippets.

@cmaggard
Created June 3, 2015 18:37
Show Gist options
  • Save cmaggard/b649418859aa17320f73 to your computer and use it in GitHub Desktop.
Save cmaggard/b649418859aa17320f73 to your computer and use it in GitHub Desktop.
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
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