はしばみあきら blog

プログラミングアウトプットするブログ。202010スタート

【Rails】【Ruby】Dateを使って今月の日数を配列にして表示

Railsでアプリを作っていて、今カレンダーのような機能を作るフェーズです。
色々とgemとかライブラリを探してみたけど自分の求めているものが見つからない。
自作することにしました。

Dateを使って今月の日数を配列にする

RailsはそもそもRubyなのでRubyの構文使ってバンバン書いていきます。

Dateを使っていきます。DateはRubyの時間や曜日を色々扱えるものです。

このあたりの記事がとてもわかりやすいです。
RubyとRailsにおけるTime, Date, DateTime, TimeWithZoneの違い

まずは現在の時間を出します

コントローラの中で記述しています。

Date.current

ターミナルだとこんな感じで

[3] pry(#<WorkdaysController>)> Date.current
=> Wed, 16 Dec 2020

次に今月の始めを出します。

Date.current に beginning_of_month をつけることで今月の最初の日を取得できます。

Date.current.beginning_of_month
[5] pry(#<WorkdaysController>)> Date.current.beginning_of_month
=> Tue, 01 Dec 2020

次に配列を作ります。1ヶ月は大体30日ですが、前後2~3日まで表示することを考えて35日分の表示になるよう配列を作ります。

Array.new(35){|i|i}

Array.newで配列の新規作成、(35)は配列の中身の数です。{ |i| i } とすることで i が1ずつ増えながら配列を作ることができます。

[6] pry(#<WorkdaysController>)> Array.new(35){|i|i}
=> [0, 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, 32, 33, 34]

次に wday というものを使います。これは、その日の曜日を数字に変換するものです。
["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]の順で、0,1,2,3,4,5,6で入ります。

Date.current.beginning_of_month.wday
[2] pry(#<WorkdaysController>)> Date.current.wday
=> 3

今日(2020/12/16)は水曜日なので、配列の4番目に当たる水曜日が数字で返されます。
4番目なので、0から数えて3になります。

今月初めの日の曜日を取得します。

Date.current.beginning_of_month.wday
[9] pry(#<WorkdaysController>)> Date.current.beginning_of_month.wday
=> 2

35の配列から、この数字を引いた日をスタートとします。

Array.new(35){|i|i - Date.current.beginning_of_month.wday}
[10] pry(#<WorkdaysController>)> Array.new(35){|i|i - Date.current.beginning_of_month.wday}
=> [-2, -1, 0, 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, 32]

今月と、前後数日が入る配列ができたので、ここに日付として入れるようにしていきます。

Array.new(35){ |i| Date.current.beginning_of_month + ( i -  Date.current.beginning_of_month.wday)}
[13] pry(#<WorkdaysController>)> Array.new(35){ |i| Date.current.beginning_of_month + ( i -  Date.current.beginning_of_month.wday)}
=> [Sun, 29 Nov 2020,
 Mon, 30 Nov 2020,
 Tue, 01 Dec 2020,
 Wed, 02 Dec 2020,
 Thu, 03 Dec 2020,
 Fri, 04 Dec 2020,
 Sat, 05 Dec 2020,
 Sun, 06 Dec 2020,
 Mon, 07 Dec 2020,
 Tue, 08 Dec 2020,
 Wed, 09 Dec 2020,
 Thu, 10 Dec 2020,
 Fri, 11 Dec 2020,
 Sat, 12 Dec 2020,
 Sun, 13 Dec 2020,
 Mon, 14 Dec 2020,
 Tue, 15 Dec 2020,
 Wed, 16 Dec 2020,
 Thu, 17 Dec 2020,
 Fri, 18 Dec 2020,
 Sat, 19 Dec 2020,
:

コードがものすごく長くなってしまいました。
ここまでを変数に代入しながらまとめます。

  def month

    # 現在の曜日と年月日
    date_now = Date.current

    firstDay = date_now.beginning_of_month
    firstDayIndex = firstDay.wday
    @calender = Array.new(35){|i| firstDay (i - firstDayIndex)}
  end

この変数をview側に渡してやります ちなみにslimとbootstrapを導入しています

h1 月間表

p = @month_now

table.table.table-bordered
  thead
    tr
      th 月日
      - @calender.each do |c|
       td = "#{c.month}/#{c.day}"

f:id:hashibamiakira:20201216214851p:plain

前月末からの表示ができました。

次に曜日を足します。
コントローラに少し足します。

  def month
    # 現在の曜日と年月日
    date_now = Date.current

    @weeks = ["", "", "", "", "", "", ""]

    firstDay = date_now.beginning_of_month
    firstDayIndex = firstDay.wday
    @calender = Array.new(35){|i| firstDay + (i - firstDayIndex)}
  end

@weeksに曜日を文字として入れる配列を作りました

これをviewに渡して、曜日を表示させます

h1 月間表

p = @month_now

table.table.table-bordered
  thead
    tr
      th 月日
      - @calender.each do |c|
       td = "#{c.month}/#{c.day}"

  thead
    tr
      th 曜日
      - @calender.each do |c|
        td = @weeks[c.wday]

f:id:hashibamiakira:20201216215249p:plain

@calenderの配列を回して、@weeksの配列の番号と、cに代入された日のwdayで探します。

これで1ヶ月分の表示ができました

またボチボチ更新していきます。