IT's not Rocket Science!

プログラミング難しいけど頑張ろうね!

Rubyでカレンダーを作ったメモ。前編

フィヨルドブートキャンプのRubyのプラクティスで初めて作ったものが、FizzBuzz問題でした。 その次がカレンダー作成でした。

日報に、学んだことを書いていますが、個人的にそれをまとめたいので、記事にしていきます。 完全にネタバレなので、学習中の方、参考にする方は注意して読んでください。

カンニング防止として、コードは少なめにしてあります。

作りたいもの

  • ターミナルでcalと打った時に表示されるカレンダーの形。
  • ターミナルで./cal.rb -y 1998 -m 2のように入力したら、1998年2月のカレンダーが表示されるようにする。

下の画像はすでに完成したものを表示しています。

当日の色の反転はしません。

やりたいこと

  • 日付や時間を出せるようにして日付を操る
  • 1ヶ月分の日にちを出せるようにする
  • 西暦と月、曜日を表示する
  • 日を改行させる
  • 1週間目の日の場所を合わせる

日付や時間を出せるようにして日付を操る

Dateクラスを利用する。

class Date (Ruby 3.3 リファレンスマニュアル)

一次情報であるリファレンスマニュアルをできる限り読みましょう。私は、読み方がわからなかったので、リファレンスを避けていました。そして、遠回りした結果、結局、読まざるを得なくなりました。笑

いずれ必要になりますので、「読んでも難しい!」という方は、伊藤淳一さんが素晴らしいものを書いてくださっているので、Rubyの公式リファレンスが読めるようになる本を読んで勉強するのがおすすめです。 読んでよかった!

以下、日にちの表示の仕方です。

require 'date' # Dateクラスを読み込める

today = Date.today # 執筆日であるDate: 2024-02-25が返ってくる

# dateを使って、今の年月を表示できる
year = today.year
month = today.month

昨日を出力したい場合、

# 1を引く
p yesterday = Date.today-1 # => Date: 2024-02-24

# 今日を起点にすれば数字を変えて○日後、前が出せる
p Date.today+4 # 4日後
p Date.today-3 # 3日前

月を跨いでも、対応します。

1ヶ月分の日にちを出せるようにする

日にちの出し方がわかったので、カレンダーに近づくため、1ヶ月単位である約30日間を出したいです。 しかし、今日は毎日変わるので、加減法で月初と月末は出せません。 そこで、Ruby で月末、月初を取得 - Just do ITを参考にしました。

月初と月末、そして、配列で月初から月末まで表示できるようになりました。

eachのリファレンスArray#each (Ruby 3.3 リファレンスマニュアル)

配列のリファレンスclass Array (Ruby 3.3 リファレンスマニュアル)

日にちだけが必要なのに、西暦と月が出てしまうので、.dayにして日にちのみの出力にします。

(first_day..last_day).each do |date|
 puts date.day
end

putsとprint

putsで出力すると、

1
2
3
# 以下略

改行されてしまいます。 一方、printで出力すると

1234567891011121314151617181920212223242526272829

改行されません。

曜日毎に整えられた日にち表示は後に回します。

西暦と月、曜日を表示する

西暦と月

このように月と西暦を出したいです。 Date#strftime (Ruby 3.3 リファレンスマニュアル) を使いました。

first_day.strftime() 

のように使います。

todayでも大丈夫ですね。

日本語のカレンダーだとこうならないみたい。

"#{}”

を使うのが良さそうです。

私のMacbookだと英語表記なので上でやります。

曜日

次は、曜日の表示です。 ここの部分は変化しないので、手入力でもいいとは思いますが、メソッドを見つけたので、使いました。

class Date - Documentation for Ruby 3.3

Date::ABBR_DAYNAMESはSunのような3字での曜日の省略を配列として持っています。 やりたいことは、2字なのでいじります。 ちなみに言葉の意味としては、abbreviationの省略と曜日です。

配列の全ての要素に処理をして新しい配列を作るmapメソッドを使います。

Date::ABBR_DAYNAMES.map { |day| day[0, 2] }.join(' ') # =>Su Mo Tu We Th Fr Sa

joinメソッドで配列の間にスペースを入れました。

これで、西暦・月・曜日の表示ができました。

長くなったので、ここまでにします。 次はカレンダーのような見た目にしていく方法です。