『たのしいruby 第4版』 第20章 TimeクラスとDateクラス
第20章 TimeクラスとDateクラス
模範解答はこちら
(1)
問題
「"2013年5月30日午後8時17分50秒"」といったように、「年・月・日・時・分・秒」を使った時刻の文字列を Time オブジェクトに変換して返す jparsedate メソッドを定義しろ、という問題です。
私的解答
require 'time' require 'date' def jparsedate(str) ary = str.split(/\D+/) year = ary[0] month = ary[1] day = ary[2] if str =~ /午後|pm/i hour = ary[3].to_i + 12 else hour = ary[3] end min = ary[4] sec = ary[5] Time.mktime(year, month, day, hour, min, sec) end p jparsedate("2013年5月30日午後8時17分50秒") #=> 2013-05-30 20:17:50 +0900
まず、与えられた文字列を数字以外の部分(=漢字部分)で区切って配列にします。
こうすることで単純にインデックス通りに「年・月・日・時・分・秒」になるのですが、「時」だけはちょっと工夫がいります。
午前午後を正規表現で判断して、午後かpmが含まれていれば12を足して24時間表記に直しています。
(2)
問題
Unix の「ls -t」コマンドのように、指定ディレクトリの下にあるファイルを時刻の順に並べ替える ls_t メソッドを定義しろ、という問題です。
私的解答
require 'time' require 'date' def ls_t(path) ary = [] returnStr = '' Dir.open(path) do |dir| dir.each do |name| if FileTest.file?(name) ary << name end end end ary.sort_by!{|item| File.ctime(item)}.each do |str| returnStr << "#{ary.index(str)+1}番目: #{str}\n" end returnStr end puts ls_t("./")
ディレクトリを開いて、ファイルを空の配列に追加していきます。
それを sort_by メソッドを用いて最後に更新された順に並べ替え、空の文字列に追加していきます。
(3)
問題
Date クラスを用いて今月の1日と月末の日付と曜日を求め、以下のような形式でカレンダーを表示させろ、という問題です。
Sep 2014 Su Mo Tu We Th Fr St 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
私的解答
この問題はかなり骨が折れました。。。
なので(?)、ほとんどこちらを参考にさせていただきました。
以下、上記のブログを参考にしつつ自分なりにアレンジしました。
require 'time' require 'date' class Calender def initialize(year=Date.today.year, month=Date.today.month) @firstDay = Date.new(year, month, 1) @lastDay = Date.new(year, month, -1).day @wday = @firstDay.wday @weeks = (@wday + @lastDay + 6) / 7 end def calAry calAry = (0...@weeks).map do |i| day = i * 7 - @wday + 1 if day <= 0 [nil] * @wday + (1..7 - @wday).to_a elsif day + 7 > @lastDay (day..@lastDay).to_a else (day..day + 6).to_a end end end def putCal header = @firstDay.strftime('%b') + "\s" + @firstDay.strftime('%Y') puts header.center(21) puts "Su Mo Tu We Th Fr St" calAry.each do |week| puts week.map {|d| d ? sprintf('%2d', d) : ' '}.join(' ') end end end sample = Calender.new sample.putCal
まず、年月の指定があれば、引数で指定できるようにします。デフォルトなら現時点の年月です。
次に、
@firstDay に1日の日付,
@lastDay に月末の日付,
@wady に1日の曜日,
@weeks にその月が何週間あるか,
をそれぞれインスタンス変数にぶち込みます。これは @weeks 以外はやらなくてもいいのですが、何を扱ってるのかわかりやすくするためにあえて変数を用意しました。
calAry メソッドでは、7日間ごとの配列を作っています。
if day <= 0
で最初の週を求めています。
elsif day + 7 > @lastDay
で最後の週を求めています。
putCal メソッドは、カレンダー形式に出力する部分を担っています。
変数header
に月と西暦を入れて、それを center メソッドを用いて、中央寄せで出力します。
曜日は普通に出力して、日付は一週間ごとの配列 calAry を each メソッドで1つずつ取り出したものを三項演算子を用いつつ sprintf メソッドでいい感じに整えて出力します。