Tuesday, April 01, 2008

Ruby/Informix 0.7.0 released

Yesterday night Ruby/Informix 0.7.0 escaped from my hands, after a vacational sprint that allowed Ruby/Informix to get new and important capabilities. The most obvious one is the support for the INTERVAL data type.

Actually, Ruby/Informix was able to handle insertion of INTERVAL data types already, because Informix accepts an ANSI SQL standard formatted string as an INTERVAL. Today, we can still use a String or use an Interval object for storing and also for retrieving INTERVAL data.

To create an Interval object you can write the following:


Interval = Informix::Interval # for short

ym = Interval.year_to_month(2, 5) #=> "2-05"
ds = Interval.day_to_second(1, 2,
3, 4) #=> "1 02:03:04.00000"


ym is an INTERVAL YEAR TO MONTH, while ds is an INTERVAL DAY TO FRACTION.

You don't need to specify all the fields of an INTERVAL.



# the rest of the fields are zero
Interval.year_to_month(2) #=> "2-00"
Interval.day_to_second(5) #=> "5 00:00:00.00000"

# using a hash
Interval.year_to_month(:months => 3) #=> "0-03"
Interval.day_to_second(:hours => 2,
:minutes => 5) #=> "0 02:05:00.00000"



You can even use fractions of years, days, hours, minutes or seconds:


Interval.year_to_month(1.5) #=> "1-06"
Interval.day_to_second(:hours => 1.5,
:minutes => 5) #=> "0 01:35:00.00000"


You can use Rationals instead of Floats for exactitud:


# a third of an hour?, not quite
Interval.year_to_month(0.3) #=> "0 00:18:00.00000"

# this is exact
Interval.year_to_month(Rational(1,3)) #=> "0 00:20:00.00000"


This is specially important when working with small fractions of seconds:



Interval.day_to_second(:days=>123456789,
:seconds=>1.2) #=> "123456789 00:00:01.19922"
Interval.day_to_second(:days=>123456789,
:seconds=>Rational(12,10)) #=> "123456789 00:00:01.20000"


Because when using Floats, there's a limit in the significant digits that can be stored that doesn't exist when using a Rational.

Interval objects have the ability to work with Date, DateTime and Time Ruby objects:


# YEAR TO MONTH an Date
ym = Interval.year_to_month(1, 5) #=> "1-05"
today = Date.today #=> "2008-04-01"
ym + today #=> "2009-09-01"


# DAY TO SECOND and Time
ds = Interval.day_to_second(:hours=>3,
:minutes=> 10) #=> "0 03:10:00.00000"
now = Time.now #=> "2008-04-01 19:58:04.856533"
ds + now #=> "2008-04-01 23:08:04.856533"


You can't mix INTERVAL YEAR TO MONTH with Time, or INTERVAL DAY TO FRACTION with Date, because are incompatible. If you still want to do something like that, you can use DateTime:



now = DateTime.now #=> "2008-04-01 20:21:42"
ym = Interval.year_to_month(1, 5) #=> "1-05"
ds = Interval.day_to_second(:hours=>3,
:minutes=> 10) #=> "0 03:10:00.00000"

ym + now #=> "2009-09-01 20:21:42"
ds + now #=> "2008-04-01 23:31:42"


But there's still more. What about if I want to know how many minutes are in 3 days and 4 hours?



ds = Interval.day_to_second(:days=> 3,
:hours=> 4) #=> "3 04:00:00.00000"
ds.to_minutes #=> 4560.0


What about seconds



ds.to_seconds #=> 273600




There are some things left to learn about Intervals, but this post has become too long. Don't forget to check the documentation, which has been enriched with more examples.

2 comments:

Diego F Guillen-Nakamura said...

Hola Gerardo, vi tu mensaje en AkitaOnRails. Soy el autor del libro "Ruby Facil". Lo consigues en el siguiente sitio: http://www.lulu.com/content/1759456
Espero sea util para tus amigos.
Un cordial saludo,
Diego Guillen

Gerardo Santana said...

Qué tal Diego,

gracias por la dirección, ya se los he compartido a los compañeros.

Que estés bien.