Rubyで誕生日の生年月日から現在の学年を判断するプログラムを作りたいと思っています。
現在下記のプログラムですと誕生日を迎えた時点で学年が上がってしまいます。4月1日の時点で
学年が上がるようにしたいのですが、どのように修正したらいいか伺えないでしょうか。
何卒宜しくお願い申し上げます。
ruby
require "date"
puts "西暦何年にお子さんは生まれましたか"
by = gets.to_i
puts "何月にお子さんは生まれましたか"
bm = gets.to_i
puts "何日に生まれましたか"
bd = gets.to_i
birthday =Time.mktime(by,bm,bd)
age = (Date.today.strftime('%Y%m%d').to_i - birthday.strftime('%Y%m%d').to_i) / 10000
case age
when 0
puts "学校にはまだいけません。"
when 1
puts "学校にはまだいけません。"
when 2
puts "学校にはまだいけません。"
when 3
puts "幼稚園の年少です。"
when 4
puts "幼稚園の年中です。"
when 5
puts "幼稚園の年長です"
when 6
puts "小学校一年生です。"
when 7
puts "小学校二年生です。"
when 8
puts "小学校三年生です。"
when 9
puts "小学校四年生です。"
when 10
puts "小学校五年生です。"
when 11
puts "小学校六年生です。"
when 12
puts "中学校一年生です。"
when 13
puts "中学校二年生です。"
when 14
puts "中学校三年生です。"
when 15
puts "高校一年生です。"
when 16
puts "高校二年生です。"
when 17
puts "高校三年生です。"
when 18
puts "大学一年生です。"
when 19
puts "大学二年生です。"
when 20
puts "大学三年生です。"
when 21
puts "大学四年生です。"
else
puts "社会人です。"
end
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答4件
0
今日が 3 月までなら去年、4 月以降なら今年の 4/1 を基準日として年齢を考えればいいので、こんな感じでしょうか。
diff
1 birthday =Time.mktime(by,bm,bd) 2-age = (Date.today.strftime('%Y%m%d').to_i - birthday.strftime('%Y%m%d').to_i) / 10000 3+today = Date.today 4+toDate = Time.mktime(today.year - (today.month < 4 ? 1 : 0), 4, 1) 5+age = (toDate.strftime('%Y%m%d').to_i - birthday.strftime('%Y%m%d').to_i) / 10000
実行結果(なお、一学年は4月2日生まれから翌年の4月1日生まれの児童生徒までで構成される ことにご注意ください。)
$ ruby schoolYear.rb 西暦何年にお子さんは生まれましたか 2000 何月にお子さんは生まれましたか 1 何日に生まれましたか 1 大学三年生です。 $ ruby schoolYear.rb 西暦何年にお子さんは生まれましたか 2000 何月にお子さんは生まれましたか 4 何日に生まれましたか 1 大学三年生です。 $ ruby schoolYear.rb 西暦何年にお子さんは生まれましたか 2000 何月にお子さんは生まれましたか 4 何日に生まれましたか 2 大学二年生です。 $ ruby schoolYear.rb 西暦何年にお子さんは生まれましたか 2000 何月にお子さんは生まれましたか 12 何日に生まれましたか 31 大学二年生です。
ちなみに、一点バグが残ってますが、これはご自分でなんとかしてください。
$ ruby schoolYear.rb 西暦何年にお子さんは生まれましたか 2020 何月にお子さんは生まれましたか 4 何日に生まれましたか 3 社会人です。
また、余計なお世話ですが、年齢通りに進学しない人もいますし、大学に行かない人も、逆に大学を出てすぐに社会人にならない人もいますので、使いみちによってはその辺の配慮も必要かと存じます。
せっかく書いたので、テストコードを載せておきます。
ruby
1# test_sample.rb 2require 'test/unit' 3require 'date' 4 5class Sample 6 def self.age(birthday, today) 7 (today.strftime('%Y%m%d').to_i - birthday.strftime('%Y%m%d').to_i) / 10000 8 end 9 10 def self.schoolYear(birthday, today = Date.today) 11 toDate = Time.mktime(today.year - (today.month < 4 ? 1 : 0), 4, 1) 12 (toDate.strftime('%Y%m%d').to_i - birthday.strftime('%Y%m%d').to_i) / 10000 13 end 14end 15 16class TestSample < Test::Unit::TestCase 17 def test_age 18 assert_equal 20, Sample.age(Time.mktime(2000, 1, 1), Time.mktime(2020, 1, 1)) 19 20 assert_equal 19, Sample.age(Time.mktime(2000, 1, 2), Time.mktime(2020, 1, 1)) 21 assert_equal 20, Sample.age(Time.mktime(2000, 1, 2), Time.mktime(2020, 1, 2)) 22 assert_equal 20, Sample.age(Time.mktime(2000, 1, 2), Time.mktime(2020, 1, 3)) 23 24 assert_equal 19, Sample.age(Time.mktime(2000, 2, 28), Time.mktime(2020, 2, 27)) 25 assert_equal 20, Sample.age(Time.mktime(2000, 2, 28), Time.mktime(2020, 2, 28)) 26 assert_equal 20, Sample.age(Time.mktime(2000, 2, 28), Time.mktime(2020, 2, 29)) 27 assert_equal 20, Sample.age(Time.mktime(2000, 2, 28), Time.mktime(2020, 3, 1)) 28 29 assert_equal 19, Sample.age(Time.mktime(2000, 2, 29), Time.mktime(2020, 2, 28)) 30 assert_equal 20, Sample.age(Time.mktime(2000, 2, 29), Time.mktime(2020, 2, 29)) 31 assert_equal 20, Sample.age(Time.mktime(2000, 2, 29), Time.mktime(2020, 3, 1)) 32 33 assert_equal 18, Sample.age(Time.mktime(2001, 2, 28), Time.mktime(2020, 2, 27)) 34 assert_equal 19, Sample.age(Time.mktime(2001, 2, 28), Time.mktime(2020, 2, 28)) 35 assert_equal 19, Sample.age(Time.mktime(2001, 2, 28), Time.mktime(2020, 2, 29)) 36 assert_equal 19, Sample.age(Time.mktime(2001, 2, 28), Time.mktime(2020, 3, 1)) 37 38 assert_equal 20, Sample.age(Time.mktime(2000, 2, 29), Time.mktime(2021, 2, 27)) 39 assert_equal 20, Sample.age(Time.mktime(2000, 2, 29), Time.mktime(2021, 2, 28)) 40 assert_equal 21, Sample.age(Time.mktime(2000, 2, 29), Time.mktime(2021, 3, 1)) 41 end 42 43 def test_schoolYear 44 assert_equal 20, Sample.schoolYear(Time.mktime(2000, 1, 1)) 45 assert_equal 20, Sample.schoolYear(Time.mktime(2000, 2, 29)) 46 assert_equal 20, Sample.schoolYear(Time.mktime(2000, 3, 31)) 47 assert_equal 20, Sample.schoolYear(Time.mktime(2000, 4, 1)) 48 assert_equal 19, Sample.schoolYear(Time.mktime(2000, 4, 2)) 49 assert_equal 19, Sample.schoolYear(Time.mktime(2000, 5, 1)) 50 assert_equal 19, Sample.schoolYear(Time.mktime(2000, 12, 31)) 51 52 assert_equal 19, Sample.schoolYear(Time.mktime(2000, 1, 1), Date.new(2020, 1, 1)) 53 assert_equal 19, Sample.schoolYear(Time.mktime(2000, 1, 1), Date.new(2020, 3, 31)) 54 assert_equal 20, Sample.schoolYear(Time.mktime(2000, 1, 1), Date.new(2020, 4, 1)) 55 assert_equal 20, Sample.schoolYear(Time.mktime(2000, 1, 1), Date.new(2020, 4, 2)) 56 assert_equal 20, Sample.schoolYear(Time.mktime(2000, 1, 1), Date.new(2020, 12, 31)) 57 58 assert_equal 19, Sample.schoolYear(Time.mktime(2000, 4, 1), Date.new(2020, 1, 1)) 59 assert_equal 19, Sample.schoolYear(Time.mktime(2000, 4, 1), Date.new(2020, 3, 31)) 60 assert_equal 20, Sample.schoolYear(Time.mktime(2000, 4, 1), Date.new(2020, 4, 1)) 61 assert_equal 20, Sample.schoolYear(Time.mktime(2000, 4, 1), Date.new(2020, 4, 2)) 62 assert_equal 20, Sample.schoolYear(Time.mktime(2000, 4, 1), Date.new(2020, 12, 31)) 63 64 assert_equal 18, Sample.schoolYear(Time.mktime(2000, 4, 2), Date.new(2020, 1, 1)) 65 assert_equal 18, Sample.schoolYear(Time.mktime(2000, 4, 2), Date.new(2020, 3, 31)) 66 assert_equal 19, Sample.schoolYear(Time.mktime(2000, 4, 2), Date.new(2020, 4, 1)) 67 assert_equal 19, Sample.schoolYear(Time.mktime(2000, 4, 2), Date.new(2020, 4, 2)) 68 assert_equal 19, Sample.schoolYear(Time.mktime(2000, 4, 2), Date.new(2020, 12, 31)) 69 end 70end
投稿2020/04/04 05:16
編集2020/04/04 05:31総合スコア7901
0
ベストアンサー
学年が決定されるのは「4/1時点での年齢」です。
ですから、誕生日と基準となる年の4/1から、その人の年齢を計算するべきですね。
Ruby
1age = (Date.today.strftime('%Y%m%d').to_i - birthday.strftime('%Y%m%d').to_i) / 10000
ここで年齢を「今日の時点で何歳か」で計算してしまっているから学年ではなくて満年齢の計算になってしまっています。
基準は
- 今日が 4/1 以前なら、前年の4/1
- 今日が 4/2 以後なら、今年の4/1
とすればよいのでは?
投稿2020/04/06 02:31
総合スコア13703
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/04/06 05:00
2020/04/06 05:10
0
age = (Date.today.strftime('%Y%m%d').to_i - birthday.strftime('%Y%m%d').to_i) / 10000
の直後に以下の文を挿入してください。
Ruby
1 if birthday.strftime('%m%d').to_i >= "0402".to_i 2 oso_umare = true 3 else 4 oso_umare = false 5 end 6 if today.strftime('%m%d').to_i >= birthday.strftime('%m%d').to_i 7 have_birthday = true 8 else 9 have_birthday = false 10 end 11 if today.strftime('%m').to_i >= 4 12 if oso_umare == true && have_birthday == true 13 age = age - 1 14 end 15 else 16 if oso_umare == true || have_birthday == true 17 age = age - 1 18 end 19 end
hoshi-takanoriさんが指摘した通り、1学年は4月2日生まれから翌年の4月1日生まれの児童生徒で構成される前提です。
遅生まれは4月2日以降に生まれた生徒です。(oro_umare=true)
その年の誕生日を迎えた場合、have_birthday = trueとなります。
年齢算出時、
現在日が4月以降(4月含む)なら、遅生まれで、誕生日を迎えた場合、年齢から1を引きます。
現在日が3月以前(3月含む)なら、遅生まれ、又は誕生日を迎えた場合、年齢から1を引きます。
もし、1学年は4月1日生まれから翌年の3月31日生まれの児童生徒で構成される前提にしたいなら、
if birthday.strftime('%m%d').to_i >= "0402".to_i
を
if birthday.strftime('%m%d').to_i >= "0401".to_i
に変えてください。
投稿2020/04/04 00:54
編集2020/04/06 02:31総合スコア5493
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。