Too complex for me

I need help from a ruby master... it's too hard with my present understanding, any starting key will be apprciated ....

from a period range [start_date, end_date] in ayear , I need to produce a list of special days like the following :
["2006-10-12","2006-11-08"] => { 10 : [ 12 , 31], 11 : [ 1, 8] }
or
["2006-10-12","2006-12-08"] => { 10 : [ 12 , 31], 11 : [ 1, 30] , 12 : [ 1, 12] }
which means, for each month in the range
  the month number : [ period covered in the month] ,

where 'period covered in the month' is
[ 1st day of the period or 1st day of the month , last day of the period or last day of the month ]

coudl I get any clue ?

thanks a lot

joss

The first step, I would say, should be to convert your values from
strings into real Date objects.
require 'date'
d1 = Date.new 2006, 10, 12
d2 = Date.new 2006, 12, 8

date_range = (d1..d2)
date_range.each do |date|
puts date
end

You can then collect up the months and days into whatever format
you're looking for.

···

On 10/18/06, Josselin <josselin@wanadoo.fr> wrote:

I need help from a ruby master... it's too hard with my present
understanding, any starting key will be apprciated ....

from a period range [start_date, end_date] in ayear , I need to
produce a list of special days like the following :
["2006-10-12","2006-11-08"] => { 10 : [ 12 , 31], 11 : [ 1, 8] }
or
["2006-10-12","2006-12-08"] => { 10 : [ 12 , 31], 11 : [ 1, 30] , 12
: [ 1, 12] }
which means, for each month in the range
        the month number : [ period covered in the month] ,

where 'period covered in the month' is
[ 1st day of the period or 1st day of the month , last day of the
period or last day of the month ]

coudl I get any clue ?

I had to make a change to the return values. They are now an array (to
maintain order), with the first element being a string looking like
"2006-10", as the code works for multiple dates, the second element is
an array with the period covered.

Lots of special case code for handling year boundaries. I'm sure this
can be tightened up, I'd be interested to hear views as to how...

require 'date'

def coverage rg
  from = Date.parse(rg[0])
  to = Date.parse(rg[1])

  cover =

  # build a list of all month indexes we need to iterate over
  if from.year==to.year
    # trivial case, both dates fall within the same year
    month_range = (from.month..to.month )
  else
    # complex case - dates in different years

    # first year - form month to december
    month_range = (from.month..12).to_a

    # more than one year covered?
    (to.year-from.year-1).times do |year|
      # jan to dec
      month_range += (1..12).to_a
    end
    # last year - jan to to.month
    month_range += (1..to.month).to_a
  end

  y = from.year

  month_range.each do |m|
    if from < Date.new(y,m,1)
      first_day = 1
    else
      first_day = from.day
    end

    # passing -1 as the day gets the last day of the month
    end_of_month = Date.new(y,m,-1)

    if to > end_of_month
      last_day = end_of_month.day
    else
      last_day = to.day
    end

    cover << ["#{y}-#{m}",[first_day, last_day]]

    # next year?
    y +=1 if m==12
  end
  cover
end

p coverage(["2006-10-12","2008-02-12"])

Cheers,
Max

···

On 10/19/06, Josselin <josselin@wanadoo.fr> wrote:

I need help from a ruby master... it's too hard with my present
understanding, any starting key will be apprciated ....

from a period range [start_date, end_date] in ayear , I need to
produce a list of special days like the following :
["2006-10-12","2006-11-08"] => { 10 : [ 12 , 31], 11 : [ 1, 8] }
or
["2006-10-12","2006-12-08"] => { 10 : [ 12 , 31], 11 : [ 1, 30] , 12
: [ 1, 12] }
which means, for each month in the range
        the month number : [ period covered in the month] ,

where 'period covered in the month' is
[ 1st day of the period or 1st day of the month , last day of the
period or last day of the month ]

coudl I get any clue ?

thanks a lot

joss

A possible solution...

It clearly shows every step in the process. Usually, the 5
lines within the loop are reduced to 1 or 2 lines, but you'll
end up with less readable code.
Not a good idea for newbies... ;]

Notice that it isn't very efficient when handling very long
periods.

gegroet,
Erik V. - http://www.erikveen.dds.nl/

···

----------------------------------------------------------------

require "date"

start = Date.parse(ARGV.shift)
finish = Date.parse(ARGV.shift)
hash = {}

(start..finish).each do |date|
   month = [date.year, date.month]
   days = hash[month] || []
   first_day = days.shift || date.day
   last_day = date.day
   hash[month] = [first_day, last_day]
end

p start.to_s
p finish.to_s
p hash

----------------------------------------------------------------

Thanks a lot I'll work on it today...

joss

···

On 2006-10-19 00:37:43 +0200, "Max Muermann" <ruby@muermann.org> said:

On 10/19/06, Josselin <josselin@wanadoo.fr> wrote:

I need help from a ruby master... it's too hard with my present
understanding, any starting key will be apprciated ....

from a period range [start_date, end_date] in ayear , I need to
produce a list of special days like the following :
["2006-10-12","2006-11-08"] => { 10 : [ 12 , 31], 11 : [ 1, 8] }
or
["2006-10-12","2006-12-08"] => { 10 : [ 12 , 31], 11 : [ 1, 30] , 12
: [ 1, 12] }
which means, for each month in the range
        the month number : [ period covered in the month] ,

where 'period covered in the month' is
[ 1st day of the period or 1st day of the month , last day of the
period or last day of the month ]

coudl I get any clue ?

thanks a lot

joss

I had to make a change to the return values. They are now an array (to
maintain order), with the first element being a string looking like
"2006-10", as the code works for multiple dates, the second element is
an array with the period covered.

Lots of special case code for handling year boundaries. I'm sure this
can be tightened up, I'd be interested to hear views as to how...

require 'date'

def coverage rg
  from = Date.parse(rg[0])
  to = Date.parse(rg[1])

  cover =

  # build a list of all month indexes we need to iterate over
  if from.year==to.year
    # trivial case, both dates fall within the same year
    month_range = (from.month..to.month )
  else
    # complex case - dates in different years

    # first year - form month to december
    month_range = (from.month..12).to_a

    # more than one year covered?
    (to.year-from.year-1).times do |year|
      # jan to dec
      month_range += (1..12).to_a
    end
    # last year - jan to to.month
    month_range += (1..to.month).to_a
  end

  y = from.year

  month_range.each do |m|
    if from < Date.new(y,m,1)
      first_day = 1
    else
      first_day = from.day
    end

    # passing -1 as the day gets the last day of the month
    end_of_month = Date.new(y,m,-1)

    if to > end_of_month
      last_day = end_of_month.day
    else
      last_day = to.day
    end

    cover << ["#{y}-#{m}",[first_day, last_day]]

    # next year?
    y +=1 if m==12
  end
  cover
end

p coverage(["2006-10-12","2008-02-12"])

Cheers,
Max