如何在透视日获得日期?

时间:2015-04-28 01:44:29

标签: ruby terminal calendar

我怎样才能获得每天的日期/数字?这是我的代码:

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 We Th Fr Sa"
    month    = "#{month_names} #{year}"
    output   = [
       month.center(weekdays.size),
       weekdays
    ].join("\n")
    (1..length).each do |day|
      output << day.to_s
    end
    output
  end
end

以下是我的结果。

January 2017
Su Mo Tu We Th Fr Sa12345678910111213141516171819202122232425262728293031

3 个答案:

答案 0 :(得分:2)

由于您的问题已经被诊断出来,我将限制我的答案,以展示如何使用课程Date

<强>代码

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

[编辑:在他的回答here中,@ spickerman表达了当月的天数:Date.new(year,month,-1).day。更好,是吗?]

<强>实施例

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

<强>解释

考虑第二个例子:

year = 2015
month = 4

首先打印标题:

title = "#{Date::MONTHNAMES[month]}, #{year}".center(7*DAY_WIDTH)
  #=> "April, 2015".center(28)
  #=> "        April, 2015         " 
puts "\n#{title}"

接下来打印星期几标题:

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

例如,"Sun".rjust(4)" #=> " Sun"

现在我们需要打印每周的日子。我分两步完成了这项工作:首先创建一个要打印的数组天数,包括第一周的0-6个空格,然后打印每组七个元素:

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

我们现在将arr分成七个一组并打印每个:

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

例如:

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

2015年4月的天数计算如下:

(((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), a rational number equal to 30

答案 1 :(得分:0)

您只是忘了在日期中添加空格和换行符。尝试使用这样的东西:

def to_s
    weekdays = "Su Mo Tu We Th Fr Sa"
    month    = "#{month_names} #{year}"

    output   = [
        month.center(weekdays.size),
        weekdays
    ].join("\n")
    output << "\n"

    i = 0
    (1..length).each do |day|
        i += 1
        output << day.to_s
        if day.to_s.length == 1
            output << '  '
        else
            output << ' '
        end
        if i == 7
            i = 0
            output << "\n"
        end
    end

    output
end

我添加了第一个if语句来处理单个长度(1-9)日期&#39;间隔,第二个是每周后处理换行符(\n)。

以:

运行
Month.new(1, 2017).to_s

您的输出将是:

    January 2017    
Su Mo Tu We Th Fr Sa
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 31 

此外,在旁注中,不要忘记闰年(2月有29天)。

答案 2 :(得分:0)

如果你不关心周日没有开始的月份(就像你在this comment中提到的那样),你可以这样做:

def to_s
  wdays  = "Su Mo Tu We Th Fr Sa"
  month  = "#{month_names} #{year}"
  output = [ month.center(wdays.size), wdays]

  (1..length).each_slice(7) do |week|
    output << week.map { |day| day.to_s.rjust(2) }.join(' ')
  end

  output.join("\n")
end

使用each_slice(7)将所有31天的阵列切片为7天(一周)的子阵列。调用map将子数组中的每一天先转换为字符串(to_s),然后再确保处理单个数字的对齐(rjust(2))。使用单个空格加入一周内的所有日子。