Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
like image 638
andreofthecape Avatar asked Nov 21 '14 09:11

andreofthecape


2 Answers

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
like image 86
joelparkerhenderson Avatar answered Nov 07 '22 06:11

joelparkerhenderson


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
like image 34
Uri Agassi Avatar answered Nov 07 '22 06:11

Uri Agassi