ruby - How can i get the dates to fall on the perspective day? -


how can day/number go under each day? code below:

class month   attr_reader :month, :year    def initialize( month, year)     @month = month     @year = year   end    def month_names     names_of_months = {1 => 'january', 2 => 'february', 3 => 'march', 4 => 'april', 5 => 'may', 6 => 'june', 7 => 'july', 8 => 'august', 9 => 'september', 10 => 'october', 11 => 'november', 12 => 'december'}     return names_of_months[@month]   end    def length    days_of_months  = {1 => 31, 2 => 28, 3 => 31, 4 => 30, 5 => 31, 6 => 30, 7 => 31, 8 => 31, 9 => 30, 10 => 31, 11 => 30, 12 => 31}    return days_of_months[@month]   end    def to_s     weekdays = "su mo tu th fr sa"     month    = "#{month_names} #{year}"     output   = [        month.center(weekdays.size),        weekdays     ].join("\n")     (1..length).each |day|       output << day.to_s     end     output   end end 

below result.

january 2017 su mo tu th fr sa12345678910111213141516171819202122232425262728293031 

as problem has been diagnosed, limit answer showing how make use of class date.

code

require 'date' day_width = 4  def calendar(year, month)   title = "#{date::monthnames[month]}, #{year}".center(7*day_width)   puts "\n#{title}"   date::abbr_daynames.each { |s| print s.rjust(day_width) }   puts   arr = [*[' ']*date.new(year,month).wday, *1..days_in_month(year,month)]   arr.each_slice(7) { |week|     week.each { |d| print d.to_s.rjust(day_width) }; puts } end  def days_in_month(year,month)   (((month==12) ? date.new(year+1,1) : date.new(year,month+1)) -     date.new(year,month)) end 

[edit: in answer here, @spickerman expressed number of days in month thus: date.new(year,month,-1).day. better,eh?]

examples

calendar(2015, 2)         february, 2015         sun mon tue wed thu fri sat    1   2   3   4   5   6   7    8   9  10  11  12  13  14   15  16  17  18  19  20  21   22  23  24  25  26  27  28  calendar(2015, 4)          april, 2015           sun mon tue wed thu fri sat                1   2   3   4    5   6   7   8   9  10  11   12  13  14  15  16  17  18   19  20  21  22  23  24  25   26  27  28  29  30  calendar(2016, 2)         february, 2016         sun mon tue wed thu fri sat        1   2   3   4   5   6    7   8   9  10  11  12  13   14  15  16  17  18  19  20   21  22  23  24  25  26  27   28  29 

explanation

consider second example:

year = 2015 month = 4 

first print title:

title = "#{date::monthnames[month]}, #{year}".center(7*day_width)   #=> "april, 2015".center(28)   #=> "        april, 2015         "  puts "\n#{title}" 

next print day of week header:

date::abbr_daynames.each { |s| print s.rjust(day_width) }   #=> ["sun", "mon", "tue", "wed", "thu", "fri", "sat"].each { |s|   #=>    print s.rjust(4) }   #   sun mon tue wed thu fri sat 

for example, "sun".rjust(4)" #=> " sun".

now need print days in each week. i've done in 2 steps: first create array days printed, including 0-6 spaces in first week, print each group of 7 elements:

  arr = [*[' ']*date.new(year,month).wday, *1..days_in_month(year,month)]     #=> arr = [*[' ']*3, *1..30]     #=> arr = [*[' ', ' ', ' '], *1..30]     #=> [" ", " ", " ", 1, 2,..., 30]  

we divide arr groups of 7 , print each:

arr.each_slice(7) { |week|   week.each { |d| print d.to_s.rjust(day_width) }; puts } 

for example:

' '.to_s.d.to_s.rjust(4)    #=> '    '  10.to_s.rjust(4)    #=> '  10' 

the number of days in april, 2015 computed follows:

(((month==12) ? date.new(year+1,1) : date.new(year,month+1))-      date.new(year,month))   #=> (((4==12) ? date.new(2016,1) : date.new(2015,5))-date.new(2015,4)   #=> date.new(2015,5) - date.new(2015,4)   #=> #<date: 2015-05-01 ((2457144j,0s,0n),+0s,2299161j)> -   #<date: 2015-04-01 ((2457114j,0s,0n),+0s,2299161j)>   #=> (30/1), rational number equal 30