How do I parse a number from a String that may have a leading zero?
Question
In ruby I am parsing a date in the following format: 24092008. I want to convert each section (year, month, date) into a number.
I have split them up using a regex which produces three Strings which I am passing into the Integer constructor.
date =~ /^([\d]{2})([\d]{2})([\d]{4})/
year = Integer($3)
month = Integer($2)
day = Integer($1)
When it hits the month line it crashes as follows:
`Integer': invalid value for Integer: "09" (ArgumentError)
It took me a while to realise that it's interpreting the leading zero as Octal and 09 is not a valid Octal number (it works fine with "07").
Is there an elegant solution to this or should I just test for numbers less than 10 and remove the zero first?
Thanks.
Solution
I'm not familiar with regexes, so forgive me if this answer's off-base. I've been assuming that $3, $2, and $1 are strings. Here's what I did in IRB to replicate the problem:
irb(main):003:0> Integer("04")
=> 4
irb(main):004:0> Integer("09")
ArgumentError: invalid value for Integer: "09"
from (irb):4:in `Integer'
from (irb):4
from :0
But it looks like .to_i doesn't have the same issues:
irb(main):005:0> "04".to_i
=> 4
irb(main):006:0> "09".to_i
=> 9
OTHER TIPS
Specify base 10
Tell Ruby explicitly that you want to interpret the string as a base 10 number.
Integer("09", 10) # => 9
This is better than .to_i
if you want to be strict.
"123abc".to_i # => 123
Integer("123abc", 10) # => ArgumentError
How I figured this out
In irb
, method(:Integer)
returns #<Method: Object(Kernel)#Integer>
. That told me that Kernel
owns this method, and I looked up the documentation on Kernel. The method signature shows that it takes a base as the second argument.
Perhaps (0([\d])|([1-9][\d]))
in place of ([\d]{2})
You may have to use $2, $4, and $5 in place of $1, $2, $3.
Or if your regexp supports (?:...)
then use (?:0([\d])|([1-9][\d]))
Since ruby takes its regexp from perl, this latter version should work.