views:

883

answers:

3

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.

+8  A: 

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
Atiaxi
Yes, they are Strings - I'll edit my post shortly.
Darren Greaves
@Atiaxi: the 'invalid value' is thrown because "09" isn't a valid octal number. A leading zero typically means it is in octal, and 0-7 are the valid digits in octal. :obj.to_i converts assuming base-10.
sixlettervariables
A: 

Besides, you are using regex to tokenize the input. The parsing (assigning semantics) is done in Ruby.

xmjx
+1  A: 

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.

Jamie
Problem here is that now you have too many matches. I think the to_i approach is the best in this case, by the kiss principle
Vinko Vrsalovic