Ruby incorrectly parses 2 digit year

2020-02-26 09:02发布

问题:

Ruby correctly parses the first date but the second one is incorrect. Tested with ruby 1.9.3 and 2.1.2.

Any idea how to get it to work consistently? (We are getting in birth dates as 2 digit years)

Date.strptime("10/11/89","%d/%m/%y")
=> Fri, 10 Nov 1989

Date.strptime("15/10/63","%d/%m/%y")
=> Mon, 15 Oct 2063

回答1:

The strptime method is parsing the text "63" to the year 2063, not 1963 as you want.
This is because the method decides the century by using the POSIX standard.

The chronic gem has a similar issue because it decides the century, though differently.

A solution is to adjust the date:

d = Date.strptime("15/10/63","%d/%m/%y")
if d > Date.today
  d = Date.new(d.year - 100, d.month, d.mday)
end

In the comments of this post, Stefan suggests a good one liner:

d = d.prev_year(100) if d > Date.today 

If you need speed, you can try optimizing like this:

d <= Date.today || d = d << 1200


回答2:

When using %y in strptime, the code assumes that values under 68 are considered in the 21st century, as descirbed here:

The year within century (0-99). When a century is not otherwise specified (with a value for %C), values in the range 69-99 refer to years in the twentieth century (1969-1999); values in the range 00-68 refer to years in the twenty-first century (2000-2068).

In the chronic gem, incidentally, the cut-off year is 64:

Chronic.parse('15/10/64')
# => 1964-10-15 12:00:00 +0200

Chronic.parse('15/10/63')
# => 2063-10-15 12:00:00 +0300


回答3:

Chronic gem has added an extended support parsing 2 digit years with ambiguous_year_future_bias option:

irb(main):029:0> Chronic.parse('15/10/99', ambiguous_year_future_bias: 10)
=> 2099-10-15 12:00:00 +0300
irb(main):030:0> Chronic.parse('15/10/99', ambiguous_year_future_bias: 50)
=> 1999-10-15 12:00:00 +0300


回答4:

Add the Chronic gem to your Gemfile

gem 'chronic'

Then just parse it:

Chronic.parse("15/10/68")
=> 1968-10-15 12:00:00 -0700