LoginSignup
2
0

More than 1 year has passed since last update.

Rubyで所定の期間内のX曜日の数を計算する

Last updated at Posted at 2022-10-17

TL;DR

# 2022-10-11 ~ 2022-12-13 の間、火曜日の個数を計算する
require 'date' # Rails環境では不要

(Date.parse('2022-10-11')..Date.parse('2022-12-13')).select(&:tuesday?).size
# または
(Date.parse('2022-10-11')..Date.parse('2022-12-13')).select{ |d| d.wday == 2 }.size
=> 10

はじめて

最近はイタリア語講座に参加しました、案内ではこう書いていました。

曜日・時間: 火曜日 19:30 ~ 21:00
受講期間: 2022-10-11 ~ 2022-12-13
授業回数: 10回

しかし私は途中参加なので、果たして案内に書かれた期間に10回の授業が完了できるのか?また、休講があるのか?を懸念していました。
私は算数があんまり得意ではないので、カレンダーで数えてみましたが、なかなか正確な結果出ませんでした。
そこで、Rubyのチカラを借りたいと考えました。

解説

Rails環境で解説いたしますが、純Rubyの環境では require 'date' でライブラリーを導入すれば同じ結果になります。

日付の区間の取得

始まりの日付と終わりの日付を、..範囲オブジェクトを作ります。

(Date.parse('2022-10-11')..Date.parse('2022-12-13'))
=> Tue, 11 Oct 2022..Tue, 13 Dec 2022

範囲オブジェクトは一種のイテレーター(iterator)であり、配列と同じように、.each.mapとかが使えます。ただし、イテレーションを行うまでは展開しません。
どうしても展開したい(配列として扱いたい)場合は、.to_aで配列に転換することもできます。

(Date.parse('2022-10-11')..Date.parse('2022-12-13')).to_a
# または
[*(Date.parse('2022-10-11')..Date.parse('2022-12-13'))]
=> [Tue, 11 Oct 2022,
 Wed, 12 Oct 2022,
 Thu, 13 Oct 2022,
 Fri, 14 Oct 2022,
 ...

所定の曜日のピックアップ

RubyのDate Classは、インスタンスメソッドで .monday?.sunday? が実装されています。所定曜日のメソッドを使うか、.wdayで数字化した曜日を算出して比較します。

(Date.parse('2022-10-11')..Date.parse('2022-12-13')).select(&:tuesday?)
# または
(Date.parse('2022-10-11')..Date.parse('2022-12-13')).select{ |d| d.wday == 2 }
=> [Tue, 11 Oct 2022, Tue, 18 Oct 2022, Tue, 25 Oct 2022, Tue, 01 Nov 2022, Tue, 08 Nov 2022, Tue, 15 Nov 2022, Tue, 22 Nov 2022, Tue, 29 Nov 2022, Tue, 06 Dec 2022, Tue, 13 Dec 2022]

これで、.sizeをつけば、2022-10-11~2022-12-13の間火曜日は10個あることがわかります。

.wday.cwdayの仕様

余談ですが、RubyのDateオブジェクトの曜日番号を取得するには、.wday.cwday2つのメソッドがあります。その違いは以下になります。

  • .wday日曜日をから、0~6の数字で表示します(0は日曜日)
  • .cwday月曜日をから、1~7の数字で表示します(7は日曜日)

参考

2
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0