module Text def oxford_comma if length <= 1 then self.join(", ") elsif length == 2 then "#{self[0]} and #{self[1]}" else "#{self[0...-1].join(", ")}, and #{self[-1]}" end end def is_numeric(x) x.to_f.to_s == x end def year_s_to_year(y) y = y.to_i y += 2000 if y < 100 y end def date_to_time(d) case d when Numeric then Time.new(d) when /([a-zA-Z]+)\.? +([0-9]+)/ then month, yr = $1, $2 Time.new(yr, idx_of_month(month)) when /([0-9]+)\/([0-9]+)/ Time.new(year_s_to_year($2), $1.to_i) else raise "Unknown Date Format '#{d}'" end end def to_date(d) case d when /([0-9]+)\/([0-9]+)/ then m, y = $1.to_i, $2.to_i y = 2000+y if y < 100; Time.new(y, m) else raise "Invalid date string #{self}" end end def duration(r) if not r["start"].nil? # { "start" : x, "end" : y } # or # { "start" : x } (with y implicitly assigned the string 'present') # formatted as "x -- y" "#{r["start"]} -- #{if r["end"].nil? then "present" else r["end"] end}" elsif not r["years"].nil? # { "years" : [ y1, y2, y3, y5, ... ] } # formatted as y1, y2, y3, y5, ... # Adjacent years are coalesced: e.g., y1-y3, y5, ... buffer = [] r["years"].each do |y| y = y.to_i prev = if buffer.empty? or buffer[-1][1] != (y-1) buffer.push([y,y]) else buffer[-1][1] = y end end buffer.map { |s,e| if s == e then s.to_s else "#{s} -- #{e}" end }.join(", ") else raise "Invalid time range : #{r}" end end def idx_of_month(m) case m when "Jan", "January" then 1 when "Feb", "February" then 2 when "Mar", "March" then 3 when "Apr", "April" then 4 when "May" then 5 when "Jun", "June" then 6 when "Jul", "July" then 7 when "Aug", "August" then 8 when "Sep", "Sept", "September" then 9 when "Oct", "October" then 10 when "Nov", "November" then 11 when "Dec", "December" then 12 else raise "Unknown Month '#{m}'" end end def duration_is_since?(r, year) if not r["start"].nil? return true if r["end"].nil? return date_to_time(r["end"]).year >= year elsif not r["years"].nil? return r["years"].map {|y|y.to_i}.max >= year elsif not r["year"].nil? return r["year"].to_i >= year elsif not r["date"].nil? extracted_year = case r["date"] when /[a-z]+\. (\d\d\d\d)/ then $1 else raise "Invalid date format: #{r["date"]}" end return extracted_year.to_i >= year else raise "Invalid time range : #{r}" end end def format_money(k) if k.is_a? String return k elsif k.is_a? Numeric rest, curr = k.divmod(1000) ret = sprintf(rest > 0 ? "%03d" : "%.2f", curr) while(rest > 0) do rest, curr = rest.divmod(1000) ret = sprintf(rest > 0 ? "%03d" : "%d", curr)+","+ret end return "$#{ret}" else raise "Invalid Currency Value: #{k}" end end def address_line_1(addr) raise "Missing Street in Address: #{addr}" if addr["street"].nil? addr["street"] end def address_line_2(addr) case addr["country"] when "USA", nil raise "Missing City in Address: #{addr}" if addr["city"].nil? raise "Missing State in Address: #{addr}" if addr["state"].nil? raise "Missing Zip Code in Address: #{addr}" if addr["zip"].nil? "#{addr["city"]}, #{addr["state"]} #{addr["zip"]}" else raise "Unknown Country '#{addr["country"]}' in Address: #{addr}" end end def split_name(name) parts = name.split(/ +/) [ parts[0...-1].join(" "), # first name(s) parts[-1] # last name ] end end