# Too complex for me

**URL:** <https://www.ruby-forum.com/t/too-complex-for-me/72782>\
**Category:** Ruby\
**Created:** [October 18, 2006, 11:25pm UTC](https://www.ruby-forum.com/t/too-complex-for-me/72782 "2006-10-18T23:25:33Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Josselin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/9de0a6/32.png) [@Josselin](https://www.ruby-forum.com/u/Josselin)\
**Post date:** [October 18, 2006, 11:25pm UTC](https://www.ruby-forum.com/t/too-complex-for-me/72782/1 "2006-10-18T23:25:33Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Josselin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/9de0a6/32.png) [@Josselin](https://www.ruby-forum.com/u/Josselin)\
**Post date:** [October 19, 2006, 12:11am UTC](https://www.ruby-forum.com/t/too-complex-for-me/72782/2 "2006-10-19T00:11:41Z")

</div>

On 10/18/06, Josselin [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> ```
> 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 ?

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.

---

<div class="post-metadata">

**Author:** ![Josselin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/9de0a6/32.png) [@Josselin](https://www.ruby-forum.com/u/Josselin)\
**Post date:** [October 19, 2006, 12:39am UTC](https://www.ruby-forum.com/t/too-complex-for-me/72782/3 "2006-10-19T00:39:47Z")

</div>

On 10/19/06, Josselin [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> ```
> the month number : [period covered in the month] ,
> 
> ```

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

---

<div class="post-metadata">

**Author:** ![Josselin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/9de0a6/32.png) [@Josselin](https://www.ruby-forum.com/u/Josselin)\
**Post date:** [October 19, 2006, 10:41pm UTC](https://www.ruby-forum.com/t/too-complex-for-me/72782/4 "2006-10-19T22:41:35Z")

</div>

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/](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

---

<div class="post-metadata">

**Author:** ![Josselin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/9de0a6/32.png) [@Josselin](https://www.ruby-forum.com/u/Josselin)\
**Post date:** [October 19, 2006, 8:03am UTC](https://www.ruby-forum.com/t/too-complex-for-me/72782/5 "2006-10-19T08:03:54Z")

</div>

On 2006-10-19 00:37:43 +0200, “Max M.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) said:

> > which means, for each month in the range  
> > joss  
> > require ‘date’  
> > month\_range = (from.month…to.month )  
> > end  
> > first\_day = from.day
> 
> Cheers,  
> Max

Thanks a lot I’ll work on it today…

joss
