はじめに
この記事はRubyの初心者がアウトプットの練習をするために書いたものです。
後続の人が見て分かりやすいよう初心者なりに丁寧に解説しながら書いています。
参考元を以下に記します。
[アウトプットのネタに困ったらこれ!?Ruby初心者向けのプログラミング問題を集めてみた(全10問)]
(https://blog.jnito.com/entry/2019/05/03/121235)
問題
上記参考元より引用。
Date クラスを使って、今月の1日と月末の日付と曜日を求め、次のような形式でカレンダーを表示させてください
April 2013
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
## 方針
表示させたい日付は入力できるようにします。その日付が含まれるカレンダーを表示させるメソッドを用意してあげます。
```ruby
def calender(year,mon,day)
#ここに処理を書く
end
puts "日付を入力してください(年,月,日)"
year = gets.to_i
mon = gets.to_i
day = gets.to_i
calender(year,mon,day) #取得した年,月,日をcalenderメソッドに渡す
目標の表示は、上から年月の部分、曜日の部分、日にちの部分の3つに分けられそうです。それぞれ表示させていけば題意を満たせそうです。
年月の部分
取得した日付にstrftimeメソッドを用いることで表示させます。
top = Date.new(year,mon,day).strftime("%B %Y")
puts top
曜日の部分
配列でSu~Saを用意し、表示させれば良いです。
wday = %w(Su Mo Tu We Th Fr Sa)
puts wday.join(" ")
日にちの部分
ここは少し複雑ですので、順番に考えましょう。
まず、表示させるカレンダーの1日目が何曜日か把握する必要があります。また、最後の日付も把握する必要があります。問題にもこの2つを求めるよう指示がされています。この2つの情報がないとカレンダーを正しく表示させることができません。
firstday_wday = Date.new(year,mon,1).wday #1日目が何曜日か
lastday = Date.new(year,mon,-1).day #その月の最後の日付
次に1日目を表示させる位置を考えます。これは、1日目が何曜日かがわかっていれば、その曜日分まで空白を記述させることで実現しましょう。
print " " * firstday_wday
* firstday_wdayと記述することで、空白をfirstday_wdayの値分記述することができます。
例えば今注目している1日目が日曜日なら、firstday_wdayの値は0,空白はなし。月曜日ならその値は1で空白も1つ。と言う具合です。
次に考えるのは日にちを実際に表示させることです。1日目をスタートさせる位置は分かりました。ですので、今度は何日分の表示をすれば良いか考えます。そのために、注目している日付の最後の日にちを取得します。
lastday = Date.new(year,mon,-1).day
最後に日付を表示するコードを記述します。このとき、7日に一回(wdayが日曜日、つまり7の倍数になるたびに)改行することに留意しましょう。
firstday_wday = Date.new(year,mon,1).wday
wday = firstday_wday
(1..lastday).each do |date|
print date.to_s.rjust(2) + " "
wday += 1
if wday % 7 == 0
print "\n"
end
end
目標とする表示が右詰になっているので、日にちはrjustで右に詰めて表示させます。
毎日wdayの値を1増加させ、7の倍数になる(=日曜日)ときには改行させましょう。
感想、まとめ
これまでバラバラに書いていたコードを修正しながら掲示します。
def calender(year,mon,day)
require "date"
top = Date.new(year,mon,day).strftime("%B %Y")
firstday_wday = Date.new(year,mon,1).wday
lastday = Date.new(year,mon,-1).day
wday = %w(Su Mo Tu We Th Fr Sa)
puts top.center(20) #目標とする表示が真ん中似合わせるようになっているので
puts wday.join(" ")
print " " * firstday_wday
wday = firstday_wday
(1..lastday).each do |date|
print date.to_s.rjust(2) + " "
wday += 1
if wday % 7 == 0
print "\n"
end
end
if wday % 7 != 0 #表示が土曜日以外で終わった際に改行させる
print "\n"
end
end
puts "今日の日付を入力してください(年,月,日)"
year = gets.to_i
mon = gets.to_i
day = gets.to_i
calender(year,mon,day)
新しい記述をしたもののみ注意書きをしておきましたが、概ねはまとめまでに書いた内容が理解できればカレンダーをかけると思います。