質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

4回答

1631閲覧

rubyで一ヶ月間の日付と曜日を出力したい。

yoshimitsu41

総合スコア36

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

1クリップ

投稿2017/10/27 11:05

ruby初心者です。

やりたいことの理想形を書きます。
例えば…

ステップ1
make_day.rbというファイルを作っTerminalで実行すると
「西暦を入力して下さい。」
と出てきて「2017」と入力。

ステップ2
「月を入力して下さい」
とでてきて「10」と入力

すると
10/01日曜日
10/02月曜日
10/03火曜日
10/04水曜日
10/05木曜日
10/06金曜日
10/07土曜日
以下31日まで続く…。

というプログラムを作りたいです。

さらに
日曜日と土曜日だけ
10/01日曜日(休)
10/07土曜日(休)

といったふうに出るのが一番の理想です。

素人なりに調べて作ったのが下記でここからどのように発展させて作っていけば良いのかわかりません。
※そもそも動きませんでしたが…。

ruby

1require 'date' 2puts "年を入力してください:" 3year = gets.to_i 4puts "月を入力してください:" 5month = gets.to_i 6puts "日を入力してください:" 7day = gets.to_i 8 9d = Date.new(year, month, day) 10week = %w(日 月 火 水 木 金 土 日)[d.cwday] 11 12 13while day < 31 14puts "#{year}#{month}#{day}日は#{week}曜日です" 15day += 1 16week += 1 17end 18

お詳しい方ご教授お願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

問題点がいくつかあります。

一つ目

まずそのままのコードで動かそうとするとweek += 1でエラーが出ているのがわかると思います。
エラーメッセージ:test.rb:16:in '+': no implicit conversion of Fixnum into String (TypeError) from test.rb:16:in '<main>'

dayには10行目で入れられた曜日の名前が入っています。
そこに数字である1を足そうとするとStringとFixnumを足すことになるのでエラーが起きます。

二つめ

一ヶ月の日数は月によって違うので31にしてしまうと2月とかがうまく行かなくなってしまいます。
while文を回すには何月なので一ヶ月は何日という情報が必要になってきます。なので普通にdayを加算していくとifなどで分岐処理を書く必要が出てしまいめんどくさいです。

そこで、Dateクラスには便利なものがあって、dateクラスのメソッドのnextを叩くと次の日の情報に更新してくれます。

三つめ

weekをに代入している部分って何をしているかわかりにくいと思います。
week = %w(日 月 火 水 木 金 土 日)[d.cwday]が何をしているかというと

%w(日 月 火 水 木 金 土 日)配列を作る
[d.cwday]その日が何曜日かを調べて配列からとってくる

と言う風になっていて

%W()は配列を作るメソッドで、配列の要素をスペースで並べる

d.cwdayは月〜日曜日を1〜7で表した数字を教えてくれる

なのでやっていることは以下と同じです。

week_name = ["日", "月", "火", "水", "木", "金", "土", "日"] week = week_name[d.cwday]

またここで二つめと関わってくるのですが、一番最初のコードのようにweekを一回とってしまうと次の曜日っていうのが難しいので上のコードのようにweek_nameとweekで分けておいたほうがいいです。

ちなみにですが、cwdayは月から日を17なので配列からとってくる場合、一番最初の要素に空きが出てしまい、今回の場合日が二つあるみたいな状況になってしまいます。
そこで同じようなやつにwdayっていうのがあってこっちは日から土を0
6でとってくるので今回みたいな配列にアクセスするときには使いやすいです。

コード

以上のことと本来実装したかったものをまとめて僕なりに書いてみました。

ruby

1require 'date' 2puts "年を入力してください:" 3year = gets.to_i 4puts "月を入力してください:" 5month = gets.to_i 6 7d = Date.new(year, month, 1) 8 9week_name = %w[日 月 火 水 木 金 土] 10 11while d.month == month // 入力された月を超えたらやめる 12 str = "#{d.month}/#{d.day}#{week_name[d.wday]}曜日" 13 // 土か日曜日だったら()をつける 14 if d.wday == 0 || d.wday == 6 15 str += "(休)" 16 end 17 puts str 18 19 d = d.next 20end
変更点
  • 入力を月までにしました
  • Dateのdにはその月の情報をとってきたいので、1日にしてしまいます
  • while文の条件は入力された月と進めていった月が等しいにしています
  • if文でwdayが0か6(土か日曜日)だったらの時の処理をつけています

以上でどうでしょうか?

おまけ

もっと短くすることはできますので短くしてみてください。

投稿2017/10/27 12:17

nami634

総合スコア188

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yoshimitsu41

2017/10/28 01:54

非常に細かく解説して頂きありがとうございます!思った通りの動きが出来ました!wday知らなかったです。本当にありがとうございました!精進します。
guest

0

おもしろそうなので書いてみました

「こういう書き方もあるんだな」くらいに思っていただければ幸いです

詳細については、いちどドキュメントを参照してみてください
(今回であればDate やArray オブジェクトが持つ様々なメソッドは特に見ておくと良いかもしれません)

ruby

1require 'date' 2 3def ask_year_and_month 4 # 年月を訊いて 配列として返す 5 %w[西暦 月].map do |label| 6 print "#{label}を入力してください: " 7 gets.to_i 8 end 9end 10 11def create_monthly_days(year, month) 12 # 次の月を見て、前の日に戻すことで指定した月の最後の日数がわかる 13 first_day = 1 14 last_day_of_month = 15 Date.new(year, month, first_day).next_month.prev_day.day 16 17 # プリント処理に回しやすいようにDate オブジェクトを配列で生成 18 [*(first_day..last_day_of_month)].map do |day| # 最初の日から最後の日までの範囲を配列に展開 19 Date.new(year, month, day) 20 end 21end 22 23# 日付データをいい感じな表示になるように変換 24def prettify_date_format(date) 25 wday = %w[日 月 火 水 木 金 土][date.cwday.modulo(7)] 26 27 # TODO: 土日の場合はフォーマットの最後に "(休)" を付与できるようにする 28 "#{date.year}#{date.month}#{date.day}日は#{wday}曜日" 29end 30 31def print_days_of_month 32 # splat operator で、呼び出した関数の戻り値を直接引数にして渡す 33 days = create_monthly_days(*ask_year_and_month) 34 35 days.each do |d| 36 # 個々のデータは逐次フォーマットを変換して出力 37 puts prettify_date_format(d) 38 end 39end 40 41print_days_of_month # 処理開始

Links

(Ruby-Doc.org は英語ではあるものの、検索窓が付いてるので、知りたい単語ですぐに調べられていいです)

投稿2017/10/27 19:57

編集2017/10/27 19:59
gouf

総合スコア2321

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

参考情報

  • cal風に日本のカレンダーを表示するxcalコマンドを作った

https://www.xmisao.com/2013/09/25/xcal-display-a-japan-calendar-like-cal.html

  • 国民の祝日が分かるライブラリ

http://docs.komagata.org/4393

投稿2017/10/27 22:08

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

こちらで日付に関する便利メソッドが紹介されています。
[初心者向け] RubyやRailsでリファクタリングに使えそうなイディオムとか便利メソッドとか - Qiita
Railsの場合と紹介されていますが、active_supportrequireメソッドで読み込めば使えると思います。
ついでに、上記で紹介された便利メソッドについて、詳しく解説されているページも載せておきます。
Active Support コア拡張機能 | Rails ガイド

投稿2017/10/27 16:23

s-show

総合スコア203

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問