From: Matt Mencel on
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

From: Rob Biedenharn on
On Aug 9, 2010, at 6:09 PM, Matt Mencel wrote:
> 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
Rob(a)AgileConsultingLLC.com http://AgileConsultingLLC.com/
rab(a)GaslightSoftware.com http://GaslightSoftware.com/


From: Brian Candler on
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.
--
Posted via http://www.ruby-forum.com/.

From: Brian Candler on
Brian Candler wrote:
> 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.
--
Posted via http://www.ruby-forum.com/.

From: Matt Mencel on
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.

Matt

----- Original Message -----
From: "Brian Candler" <b.candler(a)pobox.com>
To: "ruby-talk ML" <ruby-talk(a)ruby-lang.org>
Sent: Tuesday, August 10, 2010 7:53:24 AM
Subject: Re: Error: Bignum too big to convert into `long'

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.
--
Posted via http://www.ruby-forum.com/.