前回の回答 のコードに曜日を求めるメソッドを追加してみました。
計算方法は、 1900年1月1日からの経過日を求め、それの 7 での剰余を求めて 1900年1月1日 の曜日からのズレから曜日を元まえるととしました。
... ツェラーの公式という便利なものがあるので、それを用いています。...
という方法もありますが、今回はそれは使わずに。
2 つのコードがあります。
utils.rb
utils_test.rb
utils.rb
lang
1# coding: utf-8
2
3# 便利メソッドを定義する。
4module Utils
5 # 閏年でないときの各月の日数
6 NORMAL_DAYS_OF_MINTH = {
7 1 => 31, 2 => 28, 3 => 31, 4 => 30, 5 => 31, 6 => 30,
8 7 => 31, 8 => 31, 9 => 30, 10 => 31, 11 => 30, 12 => 31
9 }.freeze
10
11 # year 年 month 月の日数を求める
12 def days(year, month)
13 check_year_month(year, month) # year, month の値範囲をチェックする。
14
15 # 閏年の2月は 29 日まである。
16 if month == 2 && leap?(year)
17 29
18 else
19 NORMAL_DAYS_OF_MINTH[month]
20 end
21 end
22
23 # 曜日の名前
24 WEEK_NAME = %w[日 月 火 水 木 金 土]
25
26 # 曜日を求める
27 def wday(year, month, day)
28 # 1900-01-01 は月曜
29 past_days(year, month, day) % 7
30 end
31
32 # 1900-01-01 からの経過日数を得る
33 def past_days(year, month, day)
34 ans = 0
35 (1...year).each do |y|
36 ans += 365
37 ans += 1 if leap?(y)
38 end
39 (1...month).each do |m|
40 ans += days(year, m)
41 end
42 ans += day
43 ans
44 end
45
46 # year が閏年かを調べる。
47 def leap?(year)
48 (year % 4 == 0) && ((year % 400 == 0) || (year % 100 != 0))
49 end
50
51 # year, month の値範囲をチェックする。
52 def check_year_month(year, month)
53 if (year < 1900) || (2038 < year) || (month < 1) || (12 < month)
54 throw ArgumentError.new("#{year}, #{month}")
55 end
56 end
57end
58
59# --- End of File ---
utils_test.rb
lang
1 coding: utf-8
2
3require 'date'
4require File.join(File.expand_path(File.dirname(__FILE__)), 'utils.rb')
5
6#--------- test ------
7include Utils
8
9TESTS = [
10 [2000, 1, 31],
11 [2000, 2, 29],
12 [2000, 3, 31],
13 [2000, 4, 30],
14 [2000, 5, 31],
15 [2000, 6, 30],
16 [2000, 7, 31],
17 [2000, 8, 31],
18 [2000, 9, 30],
19 [2000, 10, 31],
20 [2000, 11, 30],
21 [2000, 12, 31],
22
23 [2001, 1, 31],
24 [2001, 2, 28],
25 [2001, 3, 31],
26 [2001, 4, 30],
27 [2001, 5, 31],
28 [2001, 6, 30],
29 [2001, 7, 31],
30 [2001, 8, 31],
31 [2001, 9, 30],
32 [2001, 10, 31],
33 [2001, 11, 30],
34 [2001, 12, 31]
35]
36
37TESTS.each do |t|
38 ans = Utils.days t[0], t[1]
39 fail "#{t.join(' ')} != #{t[0]} #{t[1]} #{ans}" unless ans == t[2]
40end
41
42ERR_TESTS = [
43 [nil, nil, "undefined method `<' for nil:NilClass"],
44 [2000, nil, "undefined method `<' for nil:NilClass"],
45 [nil, 1, "undefined method `<' for nil:NilClass"],
46
47 [1899, 12, 'uncaught throw #<ArgumentError: 1899, 12>'],
48 [2039, 1, 'uncaught throw #<ArgumentError: 2039, 1>'],
49
50 [2000, 0, 'uncaught throw #<ArgumentError: 2000, 0>'],
51 [2000, 13, 'uncaught throw #<ArgumentError: 2000, 13>']
52]
53
54ERR_TESTS.each do |t|
55 begin
56 Utils.days t[0], t[1]
57 fail 'エラーが発生しませんでした。'
58 rescue => ex
59 raise ex.to_s + t.join(' ') if ex.to_s != t[2]
60 end
61end
62
63# Date のメソッドと結果を比較する。
64(1900..2038).each do |y|
65 # うるう年の判定
66 fail "fail leap(#{y})" unless Utils.leap?(y) == Date.new(y).leap?
67
68 # 月の日数
69 (1..12).each do |m|
70 fail "fail days(#{y}, #{m})" unless Utils.days(y, m) == ((Date.new(y, m, -1) - Date.new(y, m, 1)).to_i + 1)
71 # 曜日
72 (1..8).each do |d|
73 fail "fail wday(#{y}, #{m}, #{d})" unless Utils.wday(y, m, d) == Date.new(y, m, d).wday
74 end
75 end
76end
77
78today = Date.today
79puts "#{today} は #{WEEK_NAME[Utils.wday(today.year, today.month, today.day)]} 曜日です。"
80
81# $ rubocop days.rb
82# $ ruby days_test.rb
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。