andreofthecape
andreofthecape

Reputation: 1196

Ruby incorrectly parses 2 digit year

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

Upvotes: 9

Views: 4108

Answers (4)

Al17
Al17

Reputation: 430

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

Upvotes: 0

joelparkerhenderson
joelparkerhenderson

Reputation: 35453

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

Upvotes: 4

Uri Agassi
Uri Agassi

Reputation: 37409

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

Upvotes: 5

Ben Yee
Ben Yee

Reputation: 1595

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

Upvotes: -1

Related Questions