Error: Bignum too big to convert into `long'


M

Matt Mencel

Hi,

I've got a bit of code that I borrowed from here http://www.ruby-forum.com/topic/77821. I use it to convert MS timestamps into a ruby Time object.
It works fine on Mac/Linux, but not on a Solaris SPARC system. The error is "bignum too big to convert into `long'" and it occurs on the line that begins...
Time.at(.....)

I'm wondering if it's because SPARC is Big-Endian that I get the error?


def self.ad2time(timestamp)
ad_epoch = 116_444_736_000_000_000
ad_multiplier = 10_000_000

# DEBUG
ap ad_epoch.class
puts "TIMESTAMP: #{timestamp}"
ap timestamp.class

Time.at((timestamp.to_i - ad_epoch) / ad_multiplier)
end



On my Mac (Snow Leopard x86_64) the DEBUG output looks like this...
Fixnum < Integer
TIMESTAMP: 9223372036854775807
Net::BER::BerIdentifiedString < String

On Solaris SPARC it's this...
Bignum < Integer
TIMESTAMP: 9223372036854775807
String < Object



Looks like on Solaris it forces the 'ad_epoch' to a Bignum instead of a Fixnum? Should I try to cast it to a Fixnum on Solaris maybe?

Matt
 
Ad

Advertisements

R

Rob Biedenharn

Hi,

I've got a bit of code that I borrowed from here http://www.ruby-forum.com/topic/77821
. I use it to convert MS timestamps into a ruby Time object.
It works fine on Mac/Linux, but not on a Solaris SPARC system. The
error is "bignum too big to convert into `long'" and it occurs on
the line that begins...
Time.at(.....)

I'm wondering if it's because SPARC is Big-Endian that I get the
error?


def self.ad2time(timestamp)
ad_epoch = 116_444_736_000_000_000
ad_multiplier = 10_000_000

# DEBUG
ap ad_epoch.class
puts "TIMESTAMP: #{timestamp}"
ap timestamp.class

Time.at((timestamp.to_i - ad_epoch) / ad_multiplier)
end



On my Mac (Snow Leopard x86_64) the DEBUG output looks like this...

Ah, note the x86_64 part? That's a 64-bit system so Fixnum holds up to
(2^62)-1
Fixnum < Integer
TIMESTAMP: 9223372036854775807
Net::BER::BerIdentifiedString < String

On Solaris SPARC it's this...
Bignum < Integer
TIMESTAMP: 9223372036854775807
String < Object



Looks like on Solaris it forces the 'ad_epoch' to a Bignum instead
of a Fixnum? Should I try to cast it to a Fixnum on Solaris maybe?

Matt

I suspect your SPARC system is only 32-bit where 2^30 and beyond
becomes Bignum.

If your timestamp is a Net::BER::BerIdentifiedString, perhaps it has
other properties that would help convert it into an Integer. (Notice
that both Fixnum and Bignum are subclasses of Integer)

On a 32-bit system, the divide between Fixnum and Bignum is:

irb> 2**30-1
=> 1073741823
irb> _.class
=> Fixnum
irb> 2**30
=> 1073741824
irb> _.class
=> Bignum

So 910692730085 is far too big for a Fixnum and Time.at is likely
wanting a number of seconds since 1970. Maybe you can see a pattern
if you compare Time.now.to_i on your platform with your expected
timestamp value.

-Rob

Rob Biedenharn
(e-mail address removed) http://AgileConsultingLLC.com/
(e-mail address removed) http://GaslightSoftware.com/
 
B

Brian Candler

Try your example values in irb:

irb(main):003:0> (9223372036854775807 - 116_444_736_000_000_000) /
10_000_000
=> 910692730085
irb(main):004:0> Time.at(910692730085)
RangeError: bignum too big to convert into `long'
from (irb):4:in `at'
from (irb):4

Time.at expects number of seconds since Jan 1, 1970.

The value you have given it is some time in the year 30,828 :)

I suspect either your epoch or your multiplier is wrong.

B.
 
B

Brian Candler

Brian said:
Time.at expects number of seconds since Jan 1, 1970.

The value you have given it is some time in the year 30,828 :)

I suspect either your epoch or your multiplier is wrong.

Actually, I think you're just reading a dummy value. Note the following:

irb(main):001:0> 9223372036854775807.to_s(16)
=> "7fffffffffffffff"

(i.e. the largest possible signed 64-bit value)

A quick Google suggests the Microsoft epoch is Jan 1, 1601, and Windows
uses 100-nanosecond ticks.

Using a 64-bit machine:

irb(main):002:0> require 'time'
=> true
irb(main):003:0> Time.parse("Jan 1 1601")
=> Mon Jan 01 00:00:00 -0001 1601
irb(main):004:0> Time.parse("Jan 1 1601").to_i
=> -11644473525
irb(main):005:0> 11644473525 * 10_000_000
=> 116444735250000000

This value agrees with your epoch, within 75 leap seconds anyway.

If I use ldapsearch against an AD server, and look at attributes like
lastLogon, they give plausible answers when parsed using your function
(and succeed on a 32-bit machine)

Regards,

Brian.
 
B

Brian Candler

Matt said:
Ah...

9223372036854775807 is the timestamp value assigned to the
"accountExpires" attribute in Active Directory when any account is set
to "Never Expire".

It works fine on Linux/Mac but not on Solaris. I guess I'll just
convert that timestamp to something like 12/31/2099 23:59:59 before I
run the Time.at.

The largest Time you can have in a 32-bit value is:

irb(main):001:0> Time.at(0x7fffffff)
=> Tue Jan 19 03:14:07 +0000 2038
irb(main):002:0> Time.at(0x7fffffff+1)
RangeError: bignum too big to convert into `long'
from (irb):2:in `at'
from (irb):2
from :0

Being Ruby, you are not constrained to using a numeric value. You could
use nil, or a symbol like :never, or a custom object which has
sufficient Time-like behaviours:

Never = Object.new
def Never.to_s; "Never"; end
 
B

Brian Candler

Matt said:
Another reason for me to dislike Solaris SPARC.

You can get 64-bit Solaris SPARC can't you?

The example I posted (showing the limit for 32-bit Time) was on a 32-bit
Ubuntu machine.

Linux xxx 2.6.24-28-386 #1 Sat Jul 31 15:36:51 UTC 2010 i686 GNU/Linux

ruby 1.8.6 (2007-09-24 patchlevel 111) [i486-linux]

I'm sure an older Mac would be the same.
 
Ad

Advertisements

B

Brian Candler

Matt said:
Solaris 10 SPARC is 64bit. It may be the ruby version I have installed
was compiled for 32bit? It's an older version of 1.8.7 off of
sunfreeware.com. I noticed that sunfreeware has a newer 1.9.1 version
available there now so I think I'll upgrade ruby to 1.9.1 and see what
happens.

Remember that ruby 1.9 is a significantly different language to ruby
1.8. Unless you are lucky, or fancy modifying your app to work with 1.9
(and maybe its dependent libs too), I think you'd be better off finding
a 64-bit build of ruby 1.8.7.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top