Kerrie Durham Kerrie Durham - 3 days ago 6
Ruby Question

Trouble with Regex

The string is:

1/9/2017


My regex is:
/([0-9]{1,2})\/[0-9]{1,2}\/([0-9]{4})/


Here's my line of code:

def session_formatter(string)
if string =~ /([0-9]{1,2})\/[0-9]{1,2}\/([0-9]{4})/
year = $2
if $1 =~ /8|9|10|11/
"Fall " + year
elsif $1 =~ /1|2|3/
"Spring " + year
else
string
end
end
end


I have
1/9/2017
returned instead of
Spring 2017
and I can't figure out why. Any ideas?

Answer

Rather than deal with a regex I'd use:

str = '1/9/2017'

mm, dd, yyyy = str.split('/')
case mm.to_i
when 1, 2, 3
  "Spring #{yyyy}"
when 8, 9, 10
  "Fall #{yyyy}"
else
  str
end
# => "Spring 2017"

Regex are great but people love to use them so much they overlook ways the task could be done more simply. Not everything is a nail waiting to be hit with the regex hammer.

Splitting on / reduces the visual noise and using to_i makes it much easier to read and understand what the when are doing.

Alternately, use the Date class, which has all sorts of goodness:

require 'date'

str = '1/9/2017'

date = Date.strptime(str, '%m/%d/%Y')
case date.month
when 1, 2, 3
  "Spring #{date.year}"
when 8, 9, 10
  "Fall #{date.year}"
else
  str
end
# => "Spring 2017"

I used strptime because date formats aren't consistent around the world. Ruby, being an international language, uses the most common format dd/mm/yyyy for Date.parse(...), which can run into problems when parsing U.S.-based dates. Instead strptime lets me force the parser into using a U.S.-based mm/dd/yyyy form:

require 'date'

Date.strptime('31/12/2001', '%d/%m/%Y') # => #<Date: 2001-12-31 ((2452275j,0s,0n),+0s,2299161j)>
Date.strptime('31/12/2001', '%m/%d/%Y') # => ArgumentError: invalid date

# ~> ArgumentError
# ~> invalid date

Note that the first example falls prey to this particular problem. When dealing with dates it's really important that you know where the user is coming from if you allow them to enter a date as a free-formatted string, so you can at least guess what order the values are in. A better, more user-friendly, solution is to use a form that has a date-picker of some sort, that forces the order into what your code expects. Dealing with dates can incorrectly can cause major havoc with calculations involving time or money, and you just don't want to have that happen.

If the date is part of text in a file then it's a bit easier to deal with, because it should be consistently formatted, but the order is still important to know.

Comments