JRuby

ArgumentError using to_time string conversion

Details

  • Type: Bug Bug
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Fixed
  • Affects Version/s: JRuby 1.0.1
  • Fix Version/s: JRuby 1.0.3, JRuby 1.1RC2
  • Component/s: Core Classes/Modules
  • Labels:
    None
  • Environment:
    Darwin dhcp-umpk16-87-31.sfbay.sun.com 8.10.3 Darwin Kernel Version 8.10.3: Wed Jun 27 23:29:36 PDT 2007; root:xnu-792.23.3~1/RELEASE_I386 i386 i386
  • Number of attachments :
    2

Description

With Java 1.5.0_07 (the one included with this version of OS X) and a local build of jruby-1_0 branch, I am seeing the following behavior when using Rails to_time method to convert a String to a Time.

$ jruby script/console
Loading development environment.
>> s = 'Wed, 10 Oct 2007 11:55:23 -0700'
>> => "Wed, 10 Oct 2007 11:55:23 -0700"
s.to_time
>> ArgumentError: Argument out of range.
from /Users/nf151384/heliopolis/trunk/scm/script/../config/../config/../vendor/rails/activerecord/lib/../../activesupport/lib/active_support/core_ext/string/conversions.rb:10:in `to_time'
from (irb):2:in `binding'
from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:150:in `eval_input'
from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:70:in `signal_status'
from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:147:in `eval_input'
from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:70:in `each_top_level_statement'
from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:146:in `loop'
from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:146:in `catch'
from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:146:in `eval_input'
from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:70:in `start'
from :1:in `catch'
from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:69:in `start'
from :1

Also note the input prompts are printing out of sequence with the command output, which is a separate issue.

  1. 1414.patch
    03/Nov/07 12:14 AM
    2 kB
    Kjetil Ødegaard
  2. 1414-usec-limit.patch
    11/Nov/07 12:46 PM
    2 kB
    Kjetil Ødegaard

Activity

Hide
Nathan Fiedler added a comment -

Here it is just using jirb and ParseDate:

$ jirb
;irb(main):001:0> require 'parsedate'
=> true
irb(main):002:0> res = ParseDate.parsedate('Wed, 10 Oct 2007 11:55:23 -0700')
=> [2007, 10, 10, 11, 55, 23, "-0700", 3]
irb(main):003:0> date = Time.gm(*res)
ArgumentError: Argument out of range.
from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb/workspace.rb:52:in `eval'
from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb/workspace.rb:81:in `evaluate'
from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb/context.rb:219:in `evaluate'
from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:150:in `eval_input'
from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:70:in `signal_status'
from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:147:in `eval_input'
from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:70:in `each_top_level_statement'
from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:146:in `loop'
from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb/ruby-lex.rb:230:in `each_top_level_statement'
from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:146:in `catch'
from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb/ruby-lex.rb:229:in `each_top_level_statement'
from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:146:in `eval_input'
from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:70:in `start'
from :1:in `catch'
from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:69:in `start'
from :1
Maybe IRB bug!!

It seems that the date parser does not like this particular format. Note that "Tue Aug 28 00:37:29 2007 -0700" (JRUBY-1298) works just fine.

Show
Nathan Fiedler added a comment - Here it is just using jirb and ParseDate: $ jirb ;irb(main):001:0> require 'parsedate' => true irb(main):002:0> res = ParseDate.parsedate('Wed, 10 Oct 2007 11:55:23 -0700') => [2007, 10, 10, 11, 55, 23, "-0700", 3] irb(main):003:0> date = Time.gm(*res) ArgumentError: Argument out of range. from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb/workspace.rb:52:in `eval' from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb/workspace.rb:81:in `evaluate' from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb/context.rb:219:in `evaluate' from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:150:in `eval_input' from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:70:in `signal_status' from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:147:in `eval_input' from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:70:in `each_top_level_statement' from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:146:in `loop' from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb/ruby-lex.rb:230:in `each_top_level_statement' from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:146:in `catch' from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb/ruby-lex.rb:229:in `each_top_level_statement' from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:146:in `eval_input' from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:70:in `start' from :1:in `catch' from /usr/local/jruby-1.0.1/lib/ruby/1.8/irb.rb:69:in `start' from :1 Maybe IRB bug!! It seems that the date parser does not like this particular format. Note that "Tue Aug 28 00:37:29 2007 -0700" (JRUBY-1298) works just fine.
Hide
Charles Oliver Nutter added a comment -

I'm not sure what's actually correct here. Note that Ruby doesn't blow up on this particular parsed date, but it also doesn't handle it right:

~/NetBeansProjects/jruby $ cat test.rb
require 'parsedate'
res = ParseDate.parsedate('Wed, 10 Oct 2007 11:55:23 -0700')
p Time.gm(*res)
~/NetBeansProjects/jruby $ ruby test.rb
Wed Oct 10 11:55:23 UTC 2007

Note that the output timezone is still UTC, rather than -0700 or CST or whatever. According to the JRuby implementation of Time.gm, it's expecting to get a microsecond value where the "-0700" appears in the parsed array.

Here's the rdoc for Time.gm. Note that there's no form that takes the sequence of values parsedate seems to produce, and that the only ones that accept timezone also take weekday, year day, and a DST flag:

--------------------------------------------------------------- Time::gm
     Time.utc( year [, month, day, hour, min, sec, usec] ) => time
     Time.utc( sec, min, hour, day, month, year, wday, yday, isdst, tz
     ) => time
     Time.gm( year [, month, day, hour, min, sec, usec] ) => time
     Time.gm( sec, min, hour, day, month, year, wday, yday, isdst, tz
     ) => time
------------------------------------------------------------------------
     Creates a time based on given values, interpreted as UTC (GMT). The
     year must be specified. Other values default to the minimum value
     for that field (and may be +nil+ or omitted). Months may be
     specified by numbers from 1 to 12, or by the three-letter English
     month names. Hours are specified on a 24-hour clock (0..23). Raises
     an +ArgumentError+ if any values are out of range. Will also accept
     ten arguments in the order output by +Time#to_a+.

        Time.utc(2000,"jan",1,20,15,1)  #=> Sat Jan 01 20:15:01 UTC 2000
        Time.gm(2000,"jan",1,20,15,1)   #=> Sat Jan 01 20:15:01 UTC 2000

So perhaps Ruby is just ignoring bogus input for some parameters?

Show
Charles Oliver Nutter added a comment - I'm not sure what's actually correct here. Note that Ruby doesn't blow up on this particular parsed date, but it also doesn't handle it right:
~/NetBeansProjects/jruby $ cat test.rb
require 'parsedate'
res = ParseDate.parsedate('Wed, 10 Oct 2007 11:55:23 -0700')
p Time.gm(*res)
~/NetBeansProjects/jruby $ ruby test.rb
Wed Oct 10 11:55:23 UTC 2007
Note that the output timezone is still UTC, rather than -0700 or CST or whatever. According to the JRuby implementation of Time.gm, it's expecting to get a microsecond value where the "-0700" appears in the parsed array. Here's the rdoc for Time.gm. Note that there's no form that takes the sequence of values parsedate seems to produce, and that the only ones that accept timezone also take weekday, year day, and a DST flag:
--------------------------------------------------------------- Time::gm
     Time.utc( year [, month, day, hour, min, sec, usec] ) => time
     Time.utc( sec, min, hour, day, month, year, wday, yday, isdst, tz
     ) => time
     Time.gm( year [, month, day, hour, min, sec, usec] ) => time
     Time.gm( sec, min, hour, day, month, year, wday, yday, isdst, tz
     ) => time
------------------------------------------------------------------------
     Creates a time based on given values, interpreted as UTC (GMT). The
     year must be specified. Other values default to the minimum value
     for that field (and may be +nil+ or omitted). Months may be
     specified by numbers from 1 to 12, or by the three-letter English
     month names. Hours are specified on a 24-hour clock (0..23). Raises
     an +ArgumentError+ if any values are out of range. Will also accept
     ten arguments in the order output by +Time#to_a+.

        Time.utc(2000,"jan",1,20,15,1)  #=> Sat Jan 01 20:15:01 UTC 2000
        Time.gm(2000,"jan",1,20,15,1)   #=> Sat Jan 01 20:15:01 UTC 2000
So perhaps Ruby is just ignoring bogus input for some parameters?
Hide
Charles Oliver Nutter added a comment -

No followup, so bumping off 1.0.2.

Show
Charles Oliver Nutter added a comment - No followup, so bumping off 1.0.2.
Hide
Kjetil Ødegaard added a comment -

I've checked with MRI, and it handles an 8 argument form of 'utc' by ignoring the last two arguments
(timezone and weekday). This is probably to be compatible with parsedate, which returns an 8-element array.

MRI also allows negative usec values by overflowing.

Show
Kjetil Ødegaard added a comment - I've checked with MRI, and it handles an 8 argument form of 'utc' by ignoring the last two arguments (timezone and weekday). This is probably to be compatible with parsedate, which returns an 8-element array. MRI also allows negative usec values by overflowing.
Hide
Kjetil Ødegaard added a comment -

The attached patch handles both the 8 argument case and the negative usec case.

MRI doesn't allow usec values that don't fit in a signed int. Should we follow MRI here? I used the long min value since we already use the long max value.

Show
Kjetil Ødegaard added a comment - The attached patch handles both the 8 argument case and the negative usec case. MRI doesn't allow usec values that don't fit in a signed int. Should we follow MRI here? I used the long min value since we already use the long max value.
Hide
Charles Oliver Nutter added a comment -

Yes, we should try to mimic MRI here, especially since it's a fairly trivial feature to mimic. It seems like a small thing, but apps break for the weirdest reasons sometimes.

Show
Charles Oliver Nutter added a comment - Yes, we should try to mimic MRI here, especially since it's a fairly trivial feature to mimic. It seems like a small thing, but apps break for the weirdest reasons sometimes.
Hide
Nick Sieger added a comment -

I applied the patch to trunk, since all the tests pass. If you have additional patches, please attach them here.

Show
Nick Sieger added a comment - I applied the patch to trunk, since all the tests pass. If you have additional patches, please attach them here.
Hide
Kjetil Ødegaard added a comment -

Ok, the second patch limits usec values to signed int like MRI.

Show
Kjetil Ødegaard added a comment - Ok, the second patch limits usec values to signed int like MRI.
Hide
Thomas E Enebo added a comment -

Fixed in commit 4918 on trunk and 4919 on 1.0 branch (patch by Kjetil Ødegaard)

Show
Thomas E Enebo added a comment - Fixed in commit 4918 on trunk and 4919 on 1.0 branch (patch by Kjetil Ødegaard)

People

Vote (0)
Watch (2)

Dates

  • Created:
    Updated:
    Resolved: