Skip to content

Time::at with BigDecimal emits Java Negative Exponent exception #7324

@yaauie

Description

@yaauie

Environment Information

Provide at least:

  • JRuby version (jruby -v) and command line (flags, JRUBY_OPTS, etc)
    • jruby 9.3.4.0 (2.6.8) 2022-03-23 eff48c1ebf OpenJDK 64-Bit Server VM 11.0.14.1+1 on 11.0.14.1+1 +jit [x86_64-darwin]
  • Operating system and platform (e.g. uname -a)
    • Darwin maybe.lan 21.6.0 Darwin Kernel Version 21.6.0: Sat Jun 18 17:07:22 PDT 2022; root:xnu-8020.140.41~1/RELEASE_ARM64_T6000 arm64

Other relevant info you may wish to add:

  • Installed or activated gems: none
  • Application/framework version (e.g. Rails, Sinatra): none
  • Environment variables: N/A
  • Initial report to me was on a via Logstash on an x86_64 Windows box, but I have sought no additional info as I was able to replicate with vanilla jruby locally.

Expected Behavior

When given a BigDecimal whose equivalent value is within the bounds of normal seconds-epoch timestamps, I would expect Time.at to return an appropriate timestamp. For example, using MRI ruby 2.6.10:

╭─{ yaauie@maybe:~/src/REDACTED }
╰─● rbenv shell 2.6.10; ruby -v; ruby -rbigdecimal -e 'puts(Time.at(BigDecimal("1E2")).strftime("%Y-%m-%dT%H:%M:%S.%9N%z"))'
ruby 2.6.10p210 (2022-04-12 revision 67958) [arm64-darwin21]
1970-01-01T00:01:40.000000000+0000
[success]

Actual Behavior

An Unhandled Java exception: java.lang.ArithmeticException: Negative exponent
╭─{ yaauie@maybe:~/src/REDACTED }
╰─● rbenv shell jruby-9.3.4.0; ruby -v; ruby -rbigdecimal -e 'puts(Time.at(BigDecimal("1E2")).strftime("%Y-%m-%dT%H:%M:%S.%9N%z"))'
jruby 9.3.4.0 (2.6.8) 2022-03-23 eff48c1ebf OpenJDK 64-Bit Server VM 11.0.14.1+1 on 11.0.14.1+1 +jit [x86_64-darwin]
Unhandled Java exception: java.lang.ArithmeticException: Negative exponent
java.lang.ArithmeticException: Negative exponent
                  pow at java/math/BigInteger.java:2401
                 to_r at org/jruby/ext/bigdecimal/RubyBigDecimal.java:2078
                 call at org/jruby/ext/bigdecimal/RubyBigDecimal$INVOKER$i$0$0$to_r.gen:-1
  checkFuncallDefault at org/jruby/RubyClass.java:657
       finvokeChecked at org/jruby/RubyClass.java:601
             numExact at org/jruby/RubyTime.java:313
                  at1 at org/jruby/RubyTime.java:1409
                   at at org/jruby/RubyTime.java:1336
                 call at org/jruby/RubyTime$INVOKER$s$at.gen:-1
         cacheAndCall at org/jruby/runtime/callsite/CachingCallSite.java:372
                 call at org/jruby/runtime/callsite/CachingCallSite.java:175
      invokeOther1:at at -e:1
          RUBY$script at -e:1
                  run at -e:-1
  invokeWithArguments at java/lang/invoke/MethodHandle.java:710
                 load at org/jruby/ir/Compiler.java:114
            runScript at org/jruby/Ruby.java:1257
          runNormally at org/jruby/Ruby.java:1176
          runNormally at org/jruby/Ruby.java:1158
          runNormally at org/jruby/Ruby.java:1194
          runFromMain at org/jruby/Ruby.java:977
        doRunFromMain at org/jruby/Main.java:406
          internalRun at org/jruby/Main.java:290
                  run at org/jruby/Main.java:235
                 main at org/jruby/Main.java:207

ruby -rbigdecimal -e   6.18s user 0.63s system 189% cpu 3.601 total
[error: 1]                                                                    

For reference, on JRuby 9.1.12.0 this was a different exception (irrelevant JVM-related warnings stripped):

╭─{ yaauie@maybe:~/src/REDACTED }
╰─● rbenv shell jruby-9.1.12.0; ruby -v; ruby -rbigdecimal -e 'puts(Time.at(BigDecimal("1E2")).strftime("%Y-%m-%dT%H:%M:%S.%9N%z"))'
jruby 9.1.12.0 (2.3.3) 2017-06-15 33c6439 OpenJDK 64-Bit Server VM 11.0.14.1+1 on 11.0.14.1+1 +jit [darwin-x86_64]
ZeroDivisionError: divided by 0
    to_r at org/jruby/ext/bigdecimal/RubyBigDecimal.java:1540
      at at org/jruby/RubyTime.java:1114
  <main> at -e:1
[error: 1]

I can reproduce this with a number of BigDecimal inputs, but so far all of them have needed to be instantiated with Kernel#BigDecimal() using a string that is (a) in exponent notation with non-zero exponent and (b) whose mantissa has fewer than three (sometimes two?) digits of sub-decimal precision. Notably:

  • BigDecimal("100"), BigDecimal("100E0"), and BigDecimal("1.00E2") succeed when the equivalent BigDecimal("1E2") and BigDecimal("1.0E2") fail.
  • BigDecimal("1661189000") and BigDecimal("1661189.000E3") succeed where the equivalent BigDecimal("1661189E3") and BigDecimal("1661189.0E3") fail.
  • BigDecimal("1661189.320E3") succeeds, but the equivalent BigDecimal("1661189.32E3") fails.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions