In the year 2525

Is there a reason why Time.local can't handle dates beyond 2038? I know
that's when the number of second since 1970 exceeds 2^32, but can't a
big, strong language like Ruby handle it?

irb(main):004:0> Time.local(2038)
=> Fri Jan 01 00:00:00 Pacific Standard Time 2038

irb(main):005:0> Time.local(2039)
ArgumentError: time out of range
        from (irb):5:in `local'
        from (irb):5

···

--
Posted via http://www.ruby-forum.com/.

Jim v. Tess wrote:

Is there a reason why Time.local can't handle dates beyond 2038? I know
that's when the number of second since 1970 exceeds 2^32, but can't a
big, strong language like Ruby handle it?

Because it uses the underlying platform's time manipulation functions?
(Disclaimer: That's a wild guess.) No point reinventing the wheel in
Ruby. The numbercrunching to process Unix timestamps would probably be
rather sluggish done in Ruby if done in large quantities - and dates /
times are a rather common datatype you need to handle.

Mebbe hack around the issue by providing Ruby replacements for large
timestamps? Then again, maybe that's what the Date / DateTime classes
do. Buggered if I know, I could never remember which one did what.

David Vallner

Jim v. Tess:

irb(main):004:0> Time.local(2038)
=> Fri Jan 01 00:00:00 Pacific Standard Time 2038

irb(main):005:0> Time.local(2039)
ArgumentError: time out of range
        from (irb):5:in `local'
        from (irb):5

Never rely on future times...

RUBY_PLATFORM

=> "x86_64-linux"

Time.local(2**31-1)

=> Tue Jan 01 00:00:00 CET 2147483647

Time.local(2**31)

=> Wed Jan 01 00:00:00 CET -2147483648

n = 2147485547

=> 2147485547

Time.local(n)

=> Wed Jan 01 00:00:00 CET -2147481749

Time.local(n+1)

ArgumentError: argument out of range
        from (irb):70:in `local'
        from (irb):70

Kalman

···

from :0

Jim v. Tess wrote:

Is there a reason why Time.local can't handle dates beyond 2038? I know that's when the number of second since 1970 exceeds 2^32, but can't a big, strong language like Ruby handle it?

It works in JRuby...would that be considered an incompatibility, or is it an ok diversion from the C impl?

irb(main):001:0> Time.local(2038)
=> Fri Jan 01 00:00:00 CST 2038
irb(main):002:0> Time.local(2039)
=> Sat Jan 01 00:00:00 CST 2039
irb(main):003:0> Time.local(10191)
=> Sat Jan 01 00:00:00 CST 10191

···

--
Charles Oliver Nutter, JRuby Core Developer
headius@headius.com -- charles.o.nutter@sun.com
Blogging at headius.blogspot.com

Jim v. Tess wrote:

Is there a reason why Time.local can't handle dates beyond 2038? I know
that's when the number of second since 1970 exceeds 2^32, but can't a
big, strong language like Ruby handle it?

Because it uses the underlying platform's time manipulation functions?

Yes.

Mebbe hack around the issue by providing Ruby replacements for large
timestamps? Then again, maybe that's what the Date / DateTime classes
do. Buggered if I know, I could never remember which one did what.

Yes. DateTime uses Rational to represent time. 1 represents a day, not a second. It can be used with arbitrary dates well outside the range of Time, but it is MUCH slower. Use Time everywhere one can.

Kirk Haines

···

On Sat, 7 Oct 2006, David Vallner wrote:

David Vallner wrote:

Jim v. Tess wrote:

Is there a reason why Time.local can't handle dates beyond 2038? I know
that's when the number of second since 1970 exceeds 2^32, but can't a
big, strong language like Ruby handle it?

Because it uses the underlying platform's time manipulation functions?

And brings interesting portability issues (not only for ruby).

$ irb

RUBY_PLATFORM

=> "x86_64-linux"

Time.local(2525)

=> Mon Jan 01 00:00:00 GMT 2525

Charles Oliver Nutter wrote:

It works in JRuby...would that be considered an incompatibility, or is it an ok diversion from the C impl?

irb(main):001:0> Time.local(2038)
=> Fri Jan 01 00:00:00 CST 2038
irb(main):002:0> Time.local(2039)
=> Sat Jan 01 00:00:00 CST 2039
irb(main):003:0> Time.local(10191)
=> Sat Jan 01 00:00:00 CST 10191

In light of the x86_64 responses, I'd wager it's ok :slight_smile: I don't know what the performance is like, though, for Java's Date compared to the POSIX calls.

···

--
Charles Oliver Nutter, JRuby Core Developer
headius@headius.com -- charles.o.nutter@sun.com
Blogging at headius.blogspot.com

Hi,

···

In message "Re: In the year 2525" on Sun, 8 Oct 2006 03:16:40 +0900, Charles Oliver Nutter <Charles.O.Nutter@Sun.COM> writes:

Jim v. Tess wrote:

Is there a reason why Time.local can't handle dates beyond 2038? I know
that's when the number of second since 1970 exceeds 2^32, but can't a
big, strong language like Ruby handle it?

It works in JRuby...would that be considered an incompatibility, or is
it an ok diversion from the C impl?

I think it is an OK diversion.

              matz.

Jim v. Tess wrote:

Is there a reason why Time.local can't handle dates beyond 2038? I know
that's when the number of second since 1970 exceeds 2^32, but can't a
big, strong language like Ruby handle it?

Because it uses the underlying platform's time manipulation functions?

Yes.

Mebbe hack around the issue by providing Ruby replacements for large
timestamps? Then again, maybe that's what the Date / DateTime classes
do. Buggered if I know, I could never remember which one did what.

Yes. DateTime uses Rational to represent time. 1 represents a day, not a second. It can be used with arbitrary dates well outside the range of Time, but it is MUCH slower. Use Time everywhere one can.

DateTime sounds nice. As cool as ruby's automatic Fixnum -> Bignum
auto-conversions are, one imagines a date where even someone learning
ruby might be able to specify "puts 2**256" (can already), or
Date.years_ago( -13_700_000_000 ).to_s
=> "Big Bang"

Is it not theoretically possible to make a "fixnum->bignum-like Date",
where it would be fast until its precision was exceeded? Then morph
into a badass DateTime that could handle dinosaurs, and big bangs, etc.?

With Respect,

Bill

···

From: <khaines@enigo.com>

On Sat, 7 Oct 2006, David Vallner wrote:

you'll put us all out of work matz - think of all the contracts in 2037!

-a

···

On Sun, 8 Oct 2006, Yukihiro Matsumoto wrote:

>It works in JRuby...would that be considered an incompatibility, or is
>it an ok diversion from the C impl?

I think it is an OK diversion.

--
in order to be effective truth must penetrate like an arrow - and that is
likely to hurt. -- wei wu wei

Hi --

···

On Sun, 8 Oct 2006, Yukihiro Matsumoto wrote:

Hi,

In message "Re: In the year 2525" > on Sun, 8 Oct 2006 03:16:40 +0900, Charles Oliver Nutter <Charles.O.Nutter@Sun.COM> writes:

>Jim v. Tess wrote:
>> Is there a reason why Time.local can't handle dates beyond 2038? I know
>> that's when the number of second since 1970 exceeds 2^32, but can't a
>> big, strong language like Ruby handle it?
>
>It works in JRuby...would that be considered an incompatibility, or is
>it an ok diversion from the C impl?

I think it is an OK diversion.

It's definitely an incompatibility, though, in the sense that it has
the potential to create a category of programs that will run under
JRuby but not (original) Ruby.

David

--
                   David A. Black | dblack@wobblini.net
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

Bill Kelly wrote:

From: <khaines@enigo.com>

Jim v. Tess wrote:

Is there a reason why Time.local can't handle dates beyond 2038? I
know
that's when the number of second since 1970 exceeds 2^32, but can't a
big, strong language like Ruby handle it?

Because it uses the underlying platform's time manipulation functions?

Yes.

Mebbe hack around the issue by providing Ruby replacements for large
timestamps? Then again, maybe that's what the Date / DateTime classes
do. Buggered if I know, I could never remember which one did what.

Yes. DateTime uses Rational to represent time. 1 represents a day,
not a second. It can be used with arbitrary dates well outside the
range of Time, but it is MUCH slower. Use Time everywhere one can.

DateTime sounds nice. As cool as ruby's automatic Fixnum -> Bignum
auto-conversions are, one imagines a date where even someone learning
ruby might be able to specify "puts 2**256" (can already), or
Date.years_ago( -13_700_000_000 ).to_s
=> "Big Bang"

Is it not theoretically possible to make a "fixnum->bignum-like Date",
where it would be fast until its precision was exceeded? Then morph
into a badass DateTime that could handle dinosaurs, and big bangs, etc.?

Furthermore, what about automatic Float -> BigDecimal conversion?

···

On Sat, 7 Oct 2006, David Vallner wrote:

Ah, but that assumes people will still be using 32-bit machines then. I
don't know if I'll be around to collect, but I'd bet a tidy sum that the
"default" home computer in 2030 will be a 128-bit multicore machine.

I'm not willing to predict how much RAM or disk space it will have, or
what the operating systems, programming languages and applications will
look like. But just like the supercomputers of the mid-1980s are dwarfed
by today's laptops, I don't think it's a stretch to think that 20 years
from now, the laptops will dwarf today's supercomputers.

I guess I need to take good care of myself. :slight_smile:

···

ara.t.howard@noaa.gov wrote:

On Sun, 8 Oct 2006, Yukihiro Matsumoto wrote:

>It works in JRuby...would that be considered an incompatibility, or is
>it an ok diversion from the C impl?

I think it is an OK diversion.

you'll put us all out of work matz - think of all the contracts in 2037!

-a

dblack@wobblini.net wrote:

It's definitely an incompatibility, though, in the sense that it has
the potential to create a category of programs that will run under
JRuby but not (original) Ruby.

Except on 64-bit machines.

And don't forget that there are plenty of platform-incompatibilities already (particularly for Windows): Kernel#open, fork, shell expansion differences when using Kernel#`, FileUtils.ln, gems that require gcc & friends, etc.

Ruby doesn't wall the programmer off from the OS, and so it has to pay the price that Ruby programs might not work on every OS by default. It has the benefit of giving the programmer more freedom, though (say, for example, to <a href="http://jakarta.apache.org/commons/io/&quot;&gt;copy a frickin' file</a>), and that's good.

That said, it'd be nice if the difference between (and reason for) Time, Date, and DateTime were made a little clearer in the docs. *touches nose*

Devin

It's definitely an incompatibility, though, in the sense that it has
the potential to create a category of programs that will run under
JRuby but not (original) Ruby.

I did have a surprise like this, just a couple days ago:

Linux:

  $ ruby -ve 'p Time.now.strftime("%F %T")'
  ruby 1.8.4 (2005-12-24) [i686-linux]
  "2006-10-07 19:05:01"

Windows:

  > ruby -ve 'p Time.now.strftime("%F %T")'
  ruby 1.8.4 (2005-12-24) [i386-mswin32]
  " "

Regards,

Bill

···

From: <dblack@wobblini.net>

Suraj N. Kurapati wrote:

Furthermore, what about automatic Float -> BigDecimal conversion?

Wouldn't that only be possible if the processor reports if an IEEE
floating-point conversion / operation was inprecise / innacurate (can't
for the heck of it remember which term applies here.)

Even if that was the case, that means that say a floating point division
would take would take one attempt, report that, convert the floating
point numbers to BigDecimals, and then perform the division in Ruby.
This isn't something I'd like happening in code even casually working
with floating point numbers for performance reasons. Though it's a valid
Shiny Thing to put as an optional mode of operation.

David Vallner

Bill Kelly wrote:

From: <dblack@wobblini.net>

It's definitely an incompatibility, though, in the sense that it has
the potential to create a category of programs that will run under
JRuby but not (original) Ruby.

I did have a surprise like this, just a couple days ago:

Linux:

$ ruby -ve 'p Time.now.strftime("%F %T")'
ruby 1.8.4 (2005-12-24) [i686-linux]
"2006-10-07 19:05:01"

Windows:

> ruby -ve 'p Time.now.strftime("%F %T")'
ruby 1.8.4 (2005-12-24) [i386-mswin32]
" "

Thanks for the warning.

The moral of the story is trust ri more than man, if you care about portability:

[~] ri strftime | grep '%[FT]'
[~] man strftime | grep '%[FT]'
Reformatting strftime(3), please wait...
        %F Equivalent to %Y-%m-%d (the ISO 8601 date format). (C99)
               ing the seconds, see %T below.
        %T The time in 24-hour notation (%H:%M:%S). (SU)
        %F conversion is in C99 and POSIX 1003.1-2001.

···

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

David Vallner wrote:

Suraj N. Kurapati wrote:

Furthermore, what about automatic Float -> BigDecimal conversion?

Wouldn't that only be possible if the processor reports if an IEEE
floating-point conversion / operation was inprecise / innacurate (can't
for the heck of it remember which term applies here.)

Even if that was the case, that means that say a floating point division
would take would take one attempt, report that, convert the floating
point numbers to BigDecimals, and then perform the division in Ruby.

  I think that basically every operation on a number which doesn't have
a natural writing in base 2 would trigger the conversion. That is,
unless you do 2 * 0.5, you'll switch automatically to BigDecimal. Bad
idea. Why don't you use BigDecimal systematically, if you're really
worried about precision ?

  Cheers !

  Vince

Vincent Fourmond wrote:

David Vallner wrote:

Suraj N. Kurapati wrote:

Furthermore, what about automatic Float -> BigDecimal conversion?

Wouldn't that only be possible if the processor reports if an IEEE
floating-point conversion / operation was inprecise / innacurate (can't
for the heck of it remember which term applies here.)

Even if that was the case, that means that say a floating point division
would take would take one attempt, report that, convert the floating
point numbers to BigDecimals, and then perform the division in Ruby.

  I think that basically every operation on a number which doesn't have
a natural writing in base 2 would trigger the conversion. That is,
unless you do 2 * 0.5, you'll switch automatically to BigDecimal. Bad
idea. Why don't you use BigDecimal systematically, if you're really
worried about precision ?

Well, manually applying BigDecimal wherever necessary for
performance reasons feels like programming in C (remember floats and
doubles? /me vomits).

When I was learning Ruby, I absolutely *loved* the fact that Fixnum
automatically spills into Bignum and vice versa... good riddance to
short, int, long, and long long! Just think of how beneficial this
conceptual abstraction (I don't care how many bits it occupies, I
just want to use this integer!) has been to your code and mode of
thinking. If Ruby didn't have this, we would be manually checking
sizes, upcasting, and downcasting Fixnums and Bignums everywhere. :frowning:

I don't care so much about performance; rather, I want to write code
quickly and elegantly using conceptual abstractions. If I really
need performance, I will profile the code and re-write the slow
parts in C.

Suraj N. Kurapati wrote:

Well, manually applying BigDecimal wherever necessary for
performance reasons feels like programming in C (remember floats and
doubles? /me vomits).

Yes, but there's performance losses, and performance losses. For the
fixnum -> bignum conversion, there's a whole of two cutover numbers
where you have to convert from one to the other. For a Float ->
BigDecimal conversion, there's probably an infinity of them.

Also:

···

---

require 'bigdecimal'
require 'benchmark'

N = 1000000

Benchmark.bmbm { |test|
    test.report("Float") {
        for i in 1..N
            Math::PI / Math::E
        end
    }

    test.report("BigDecimal") {
        for i in 1..N
            BigDecimal.new(String(Math::PI)) /
      BigDecimal(String(Math::E))
        end
    }
}

---

Rehearsal ----------------------------------------------
Float 0.937000 0.000000 0.937000 ( 0.969000)
BigDecimal 30.594000 0.093000 30.687000 ( 30.922000)
------------------------------------ total: 31.624000sec

                 user system total real
Float 1.031000 0.000000 1.031000 ( 1.015000)
BigDecimal 30.453000 0.078000 30.531000 ( 30.766000)

---

That's a slowdown by a factor of 30. Which means simple decimal maths in
Ruby could be slower by at least a factor of 20 on average by my wild
guess. That's without the overhead of verifying if the result of a maths
operation can be represented in IEEE floats. Besides, even BigDecimals
lose precision eventually, and they don't have nearly as many use cases
as either arbitrary-size integers (that help prevent counter overflows),
or fast floating-point maths.

For a more "interesting" benchmark, let's see less trivial number crunching.

---

require 'bigdecimal'
require 'bigdecimal/math'
require 'benchmark'

N = 100000

include BigMath

Benchmark.bmbm { |test|
    test.report("Float") {
        for i in 1..N
            Math.log(Math::PI) / Math.log(Math::E)
        end
    }

    test.report("BigDecimal") {
        for i in 1..N
            log(BigDecimal(String(Math::PI)), 20) /
log(BigDecimal(String(Math::E)), 20)
        end
    }
}

---

Rehearsal ----------------------------------------------
Float 0.172000 0.000000 0.172000 ( 0.203000)
BigDecimal 278.641000 0.656000 279.297000 (279.422000)
----------------------------------- total: 279.469000sec

                 user system total real
Float 0.218000 0.000000 0.218000 ( 0.203000)
BigDecimal 276.266000 0.625000 276.891000 (286.234000)

---

That's a slowdown by a factor of roughly 1267... I don't need profiling
to see this would kill even casual use of nontrivial amounts of
numbercrunching.

I don't care so much about performance; rather, I want to write code
quickly and elegantly using conceptual abstractions. If I really
need performance, I will profile the code and re-write the slow
parts in C.

Which turns your proposal into "Let's make Ruby behave not like C,
crippling speed, so that everyone ends up rewriting maths code in C". I
fail to see the gain. As I said, the automagical conversion is somewhere
on my list of Potential Shiny Things. I doubt it's an essential feature
for, well, anyone. And it would be actively harmful to make it default
behaviour, or ever alter the behaviour to this in a library released
into the wild.

David Vallner