[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

making a monthly calendar...

Mikkel Bruun

2/29/2008 10:30:00 PM

Hey

I trying to do a calendar based app..

So i have a monthly view with 5 weeks of 7 days = 35 boxes...

Just like google calendar i need to show the selected month, and fill in
the blanks with the previous and next months days...

so february is ending today on a friday. So in the last 2 boxes of the
5. week i need to show march 1 and 2 and the same in the front...

I have this Month class. Which contains all the dates for a given month,
as well as references to the next and previous months....

there must be some kind of pattern im not getting bevause i keep
slamming my head against the wall on this....

anyone who have a quuck solution???

thanks!!

mikkel
--
Posted via http://www.ruby-....

24 Answers

Daniel Finnie

2/29/2008 11:08:00 PM

0

[Note: parts of this message were removed to make it a legal post.]

Something like this?

daniel@daniel-desktop:~$ cat /tmp/dats.rb
require 'date'

start_date = Date.civil(2007, 1, 27) # Must be a Sunday.
0.upto(4 * 7 - 1) do |offset| # 4 weeks
curr_date = start_date + offset
print curr_date.mday.to_s.rjust(3)
if offset % 7 == 6
puts
end
end
puts
daniel@daniel-desktop:~$ ruby /tmp/dats.rb
27 28 29 30 31 1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23

daniel@daniel-desktop:~$

The formatting is better if you run it at the command line.

Dan

On Fri, Feb 29, 2008 at 5:30 PM, Mikkel Bruun <mikkel@helenius.dk> wrote:

> Hey
>
> I trying to do a calendar based app..
>
> So i have a monthly view with 5 weeks of 7 days = 35 boxes...
>
> Just like google calendar i need to show the selected month, and fill in
> the blanks with the previous and next months days...
>
> so february is ending today on a friday. So in the last 2 boxes of the
> 5. week i need to show march 1 and 2 and the same in the front...
>
> I have this Month class. Which contains all the dates for a given month,
> as well as references to the next and previous months....
>
> there must be some kind of pattern im not getting bevause i keep
> slamming my head against the wall on this....
>
> anyone who have a quuck solution???
>
> thanks!!
>
> mikkel
> --
> Posted via http://www.ruby-....
>
>

Todd Benson

3/1/2008 7:52:00 AM

0

On Fri, Feb 29, 2008 at 4:30 PM, Mikkel Bruun <mikkel@helenius.dk> wrote:
> Hey
>
> I trying to do a calendar based app..
>
> So i have a monthly view with 5 weeks of 7 days = 35 boxes...
>
> Just like google calendar i need to show the selected month, and fill in
> the blanks with the previous and next months days...
>
> so february is ending today on a friday. So in the last 2 boxes of the
> 5. week i need to show march 1 and 2 and the same in the front...
>
> I have this Month class. Which contains all the dates for a given month,
> as well as references to the next and previous months....
>
> there must be some kind of pattern im not getting bevause i keep
> slamming my head against the wall on this....
>
> anyone who have a quuck solution???
>
> thanks!!
>
> mikkel

Here's one for fun. I'm pretty sure you don't want to use this (for
all I know, you might be laughed out of the room :), but it
demonstrates some methods...

require 'enumerator'
o = (t = Date.today).wday
c = (-1..1).inject([]) {|a, i| a << (t.month + i)}.map {|i|
1..Date.new( t.year, i, -1 ).day}.map {|i| i.to_a}
o.times {c[1].unshift c[0].pop}
c[1..2].flatten.slice(0..35).compact.each_slice(7) {|i| p i}

You'd have to tidy up the output of course (using #join or whatever).
Also, as you can see, 5 weeks doesn't necessarily cover a month. In
March's calendar for 2008, there are 6 days out of February.

Todd

Todd Benson

3/1/2008 7:56:00 AM

0

On Sat, Mar 1, 2008 at 1:51 AM, Todd Benson <caduceass@gmail.com> wrote:
> On Fri, Feb 29, 2008 at 4:30 PM, Mikkel Bruun <mikkel@helenius.dk> wrote:
> > anyone who have a quuck solution???
> >
> > thanks!!
> >
> > mikkel
>
> Here's one for fun. I'm pretty sure you don't want to use this (for
> all I know, you might be laughed out of the room :), but it
> demonstrates some methods...

[snip beginning code]

> c = (-1..1).inject([]) {|a, i| a << (t.month + i)}.map {|i|
> 1..Date.new( t.year, i, -1 ).day}.map {|i| i.to_a}

That is supposed to be one line, just so you know, if your reader
didn't pick it up right.

Todd

Mikkel Bruun

3/1/2008 8:35:00 AM

0

Todd Benson wrote:
> On Fri, Feb 29, 2008 at 4:30 PM, Mikkel Bruun <mikkel@helenius.dk>
> wrote:
>> 5. week i need to show march 1 and 2 and the same in the front...
>>
>> mikkel
>
> Here's one for fun. I'm pretty sure you don't want to use this (for
> all I know, you might be laughed out of the room :), but it
> demonstrates some methods...
>
woot, it actually works....

ive been doing ruby since 2000 but i cant undestand what the h*ll going
on there....

can you give me a walkthrough or a more humane rewrite ;-)

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

Todd Benson

3/1/2008 9:04:00 AM

0

On Sat, Mar 1, 2008 at 2:34 AM, Mikkel Bruun <mikkel@helenius.dk> wrote:
> Todd Benson wrote:
> > On Fri, Feb 29, 2008 at 4:30 PM, Mikkel Bruun <mikkel@helenius.dk>
> > wrote:
>
> >> 5. week i need to show march 1 and 2 and the same in the front...
> >>
>
> >> mikkel
> >
> > Here's one for fun. I'm pretty sure you don't want to use this (for
> > all I know, you might be laughed out of the room :), but it
> > demonstrates some methods...
> >
> woot, it actually works....
>
> ive been doing ruby since 2000 but i cant undestand what the h*ll going
> on there....
>
> can you give me a walkthrough or a more humane rewrite ;-)

Okay, changing the code...

<CODE>

require 'enumerator'
# I need that for the each_slice method later
today = Date.today
offset = today.wday
# gives me the day of the week
months_of_concern = (-1..1).inject([]) {|arr, i| arr << (today.month + i)}
# just running through -1 to 1 and adding to the current month
# it gives you last month, current month, and next month numbers
# which will be handed to months_of_concern after the block finishes
month_ranges = months_of_concern.map {|month| 1..Date.new( today.year,
month, -1 ).day}
# building ranges to later turn into arrays
# you get previous, current, and future month ranges
# the month days
# -1 is used, as Morton so excellently pointed out
# as the _last_ number
# this is common in Ruby

day_sets = month_ranges.map {|i| i.to_a}
# turning the Range objects (3 of them) into Array objects
# I should have used {|i| i.map} here because it
# would have been cuter, which is mostly disapproved
# of in production code :)

offset.times { day_sets[1].unshift day_sets[0].pop }
# Here, we're just moving the last numbers of the last
# month to the first part of this month one by one

day_sets[1..2].flatten.slice(0..35).compact.each_slice(7) {|i| p i}
# This one is actually easy to understand.
# Grab what we now have as the current month,
# tap on the ending month,
# flatten it (turn it into one big array),
# slice off the numbers that are in slots 0 to 35
# compact (there might be nils)
# each_slice simply builds arrays by
# grabbing things 7 at a time.

</CODE>

Keep in mind scope. The "i" variable is local to each block; all by
himself. It doesn't have to be "i", also.

Todd

Todd Benson

3/1/2008 9:07:00 AM

0

On Sat, Mar 1, 2008 at 3:03 AM, Todd Benson <caduceass@gmail.com> wrote:
>
> On Sat, Mar 1, 2008 at 2:34 AM, Mikkel Bruun <mikkel@helenius.dk> wrote:
> > Todd Benson wrote:
> > > On Fri, Feb 29, 2008 at 4:30 PM, Mikkel Bruun <mikkel@helenius.dk>
> > > wrote:
> >
> > >> 5. week i need to show march 1 and 2 and the same in the front...
> > >>
> >
> > >> mikkel
> > >
> > > Here's one for fun. I'm pretty sure you don't want to use this (for
> > > all I know, you might be laughed out of the room :), but it
> > > demonstrates some methods...
> > >
> > woot, it actually works....
> >
> > ive been doing ruby since 2000 but i cant undestand what the h*ll going
> > on there....
> >
> > can you give me a walkthrough or a more humane rewrite ;-)
>
> Okay, changing the code...
>
> <CODE>
>
> require 'enumerator'
> # I need that for the each_slice method later
> today = Date.today
> offset = today.wday
> # gives me the day of the week
> months_of_concern = (-1..1).inject([]) {|arr, i| arr << (today.month + i)}
> # just running through -1 to 1 and adding to the current month
> # it gives you last month, current month, and next month numbers
> # which will be handed to months_of_concern after the block finishes
> month_ranges = months_of_concern.map {|month| 1..Date.new( today.year,
> month, -1 ).day}
> # building ranges to later turn into arrays
> # you get previous, current, and future month ranges
> # the month days
> # -1 is used, as Morton so excellently pointed out
> # as the _last_ number
> # this is common in Ruby
>
> day_sets = month_ranges.map {|i| i.to_a}
> # turning the Range objects (3 of them) into Array objects
> # I should have used {|i| i.map} here because it
> # would have been cuter, which is mostly disapproved
> # of in production code :)
>
> offset.times { day_sets[1].unshift day_sets[0].pop }
> # Here, we're just moving the last numbers of the last
> # month to the first part of this month one by one
>
> day_sets[1..2].flatten.slice(0..35).compact.each_slice(7) {|i| p i}
> # This one is actually easy to understand.
> # Grab what we now have as the current month,
> # tap on the ending month,
> # flatten it (turn it into one big array),
> # slice off the numbers that are in slots 0 to 35
> # compact (there might be nils)
> # each_slice simply builds arrays by
> # grabbing things 7 at a time.
>
> </CODE>
>
> Keep in mind scope. The "i" variable is local to each block; all by
> himself. It doesn't have to be "i", also.

My apologies, this was aimed at newbies, not at you.

Todd

Mikkel Bruun

3/1/2008 11:45:00 AM

0

Todd Benson wrote:
> On Sat, Mar 1, 2008 at 3:03 AM, Todd Benson <caduceass@gmail.com> wrote:
>> > >
>>
>> # just running through -1 to 1 and adding to the current month
>>
>> day_sets[1..2].flatten.slice(0..35).compact.each_slice(7) {|i| p i}
>>
>> Keep in mind scope. The "i" variable is local to each block; all by
>> himself. It doesn't have to be "i", also.
>
> My apologies, this was aimed at newbies, not at you.
>
> Todd

no problem...

thanks for your reply...ill see wha i can make of it...
--
Posted via http://www.ruby-....

Todd Benson

3/1/2008 6:59:00 PM

0

On Sat, Mar 1, 2008 at 5:45 AM, Mikkel Bruun <mikkel@helenius.dk> wrote:
> Todd Benson wrote:
> > On Sat, Mar 1, 2008 at 3:03 AM, Todd Benson <caduceass@gmail.com> wrote:
> >> > >
> >>
>
> >> # just running through -1 to 1 and adding to the current month
> >>
>
> >> day_sets[1..2].flatten.slice(0..35).compact.each_slice(7) {|i| p i}
> >>
>
> >> Keep in mind scope. The "i" variable is local to each block; all by
> >> himself. It doesn't have to be "i", also.
> >
> > My apologies, this was aimed at newbies, not at you.
> >
> > Todd
>
> no problem...
>
> thanks for your reply...ill see wha i can make of it...

Thanks for the exercise. I've been meaning to make use of a graphical
calendar for a while, and now you've given me an excuse to finish it!

Todd

Todd Benson

3/3/2008 1:20:00 AM

0

Oh my goodness! A thousand apologies. I gave you a rotating month. See below.

On Sat, Mar 1, 2008 at 3:03 AM, Todd Benson <caduceass@gmail.com> wrote:
>
> On Sat, Mar 1, 2008 at 2:34 AM, Mikkel Bruun <mikkel@helenius.dk> wrote:
> > Todd Benson wrote:
> > > On Fri, Feb 29, 2008 at 4:30 PM, Mikkel Bruun <mikkel@helenius.dk>
> > > wrote:
> >
> > >> 5. week i need to show march 1 and 2 and the same in the front...
> > >>
> >
> > >> mikkel
> > >
> > > Here's one for fun. I'm pretty sure you don't want to use this (for
> > > all I know, you might be laughed out of the room :), but it
> > > demonstrates some methods...
> > >
> > woot, it actually works....
> >
> > ive been doing ruby since 2000 but i cant undestand what the h*ll going
> > on there....
> >
> > can you give me a walkthrough or a more humane rewrite ;-)
>
> Okay, changing the code...
>
> <CODE>
>
> require 'enumerator'
> # I need that for the each_slice method later
> today = Date.today

offset = Date.new(today.year, today.month, 1).wday

> # gives me the day of the week
> months_of_concern = (-1..1).inject([]) {|arr, i| arr << (today.month + i)}
> # just running through -1 to 1 and adding to the current month
> # it gives you last month, current month, and next month numbers
> # which will be handed to months_of_concern after the block finishes
> month_ranges = months_of_concern.map {|month| 1..Date.new( today.year,
> month, -1 ).day}
> # building ranges to later turn into arrays
> # you get previous, current, and future month ranges
> # the month days
> # -1 is used, as Morton so excellently pointed out
> # as the _last_ number
> # this is common in Ruby
>
> day_sets = month_ranges.map {|i| i.to_a}
> # turning the Range objects (3 of them) into Array objects
> # I should have used {|i| i.map} here because it
> # would have been cuter, which is mostly disapproved
> # of in production code :)
>
> offset.times { day_sets[1].unshift day_sets[0].pop }
> # Here, we're just moving the last numbers of the last
> # month to the first part of this month one by one
>
> day_sets[1..2].flatten.slice(0..35).compact.each_slice(7) {|i| p i}
> # This one is actually easy to understand.
> # Grab what we now have as the current month,
> # tap on the ending month,
> # flatten it (turn it into one big array),
> # slice off the numbers that are in slots 0 to 35
> # compact (there might be nils)
> # each_slice simply builds arrays by
> # grabbing things 7 at a time.
>
> </CODE>
>
> Keep in mind scope. The "i" variable is local to each block; all by
> himself. It doesn't have to be "i", also.

My original code only worked when run on the first of the month.
Pretty funny, actually. It's one of those things that a unit test
wouldn't catch unless the test was written correctly.

Todd

Mikkel Bruun

3/3/2008 8:05:00 AM

0

So I ended up with:

def calendar_view
firstday = days[0] #all days in month
offset = firstday.wday-1
boxes =Array.new(5*7) # the viewport
i=0
#this month from wday of firstday
offset.upto(days.length+offset){boxes[offset+i]=days[i];i=i+1}
i=0
#pad with previous
1.upto(offset){boxes[i]=previous.days[-offset+i];i=i+1}
i=0
#pad with next...
(offset+days.length).upto(boxes.length){boxes[days.length+i+offset]=next_month.days[i];i=i+1}
return boxes
end

I show this in a rails app using array.groups_of(7) which chops the
boxes array into parts of 7

which works ok...untill i hit june 08....where the first week starts
with jun 2nd...

How are your algorithms working??
--
Posted via http://www.ruby-....