I have strings like "84", "03"
etc. that I want to convert to Date objects, but Date.new
only takes the expanded 4-digit year as a parameter. I know it's simple to do, but I don't want to reinvent this wheel. Is there something that does this already? Either in standard Ruby or in ActiveSupport.
views:
876answers:
4I don't know of such a component, and I don't know how you'd write one; how would it decide which two-digit prefix to use? Picking a single one blindly has certain demonstrated issues.
Depending on your application, you can probably find a reasonable heuristic to pick between 19 and 20 for a prefix, but the problem isn't solvable in general; there's not enough information.
Does doing this really make sense? When should you stop considering 19xx dates? There's no good way to get a 4-digit year from the last 2-digits of the year.
Pick a cutoff date.
if year < cutoff, then year4 = "20" + year
else year4 = "19" + year
Also, fix the cause of the two digit year, or else your system won't be Y2K+cutoff compliant.
Most 2 digit years are in the past, so a good cutoff to use is 30. For example, if someone types '66, they most likely mean 1966. In fact, this is also the cutoff that Excel uses when a two digit date is passed to a date cell.
I had an application that accepted tab delimited files from excel spreadsheets, and they often came with two-digit years. I wrote this ActiveRecord monkey patch to allow ActiveRecord to handle the two digit years for date fields:
class ActiveRecord::ConnectionAdapters::Column
class << self
protected
# If a year comes in with two digits, let's try to guess whether it's in the
# 20th or 21st century. Typically, Ruby pivots this decision around the
# year '69, but this is a bad guess. Since most of our dates will arrive in
# two digit format because of an Excel import, we should use the same pivot
# value that Excel uses. Excel pivots the decision around the year '30
# which seems to be a better guess anyway.
def new_date_with_two_digit_year_support(year, mon, mday)
year += 2000 if (0..29).include? year
year += 1900 if (30..99).include? year
new_date_without_two_digit_year_support(year, mon, mday)
end
alias_method_chain :new_date, :two_digit_year_support
end
end
This isn't exactly as generic as what the question asked for, but hopefully, it helps.