レシピ1.3 日付の出力
問題
日付オブジェクトを文字列として出力したい
解決
日付を確認したいだけであれば、Time#to_sまたはDate#to_sを呼び出せば、フォーマットで面倒な思いをせずにすむ。
require 'date' Time.now.to_s # => "Sat Mar 18 19:05:50 EST 2006" DateTime.now.to_s # => "2006-03-18T19:05:50-0500"
特定のフォーマットの日付が必要である場合は、タイムフォーマットディレクティブが含まれた文字列として、そのフォーマットを定義する必要がある。フォーマット文字列をTime#strftimeまたはDate#strftimeに渡すと、フォーマットディレクティブがTimeまたはDateTimeオブジェクトの該当する部分に沖かえられた文字列が返される。
フォーマットディレクティブは、パーセント記号と文字(%x)で構成される。フォーマット文字列に含まれているフォーマットディレクティブ以外の物は全てリテラルとして扱われる。
Time.gm(2006).strftime('The year is %Y!') # => "The year is 2006!"
「解説」では、Time#strftimeとDate#strftimeによって定義された全てのタイムフォーマットディレクティブを示す。例えば、2005年12月31日午後1時30分(GMT)の日付に対する一般的なタイムフォーマット文字列は、次のようになる。
time = Time.gm(2005, 12, 31, 13, 22, 33) american_date = '%D' time.strftime(american_date) # => "12/31/05" european_date = '%d/ %m/ %y' time.strftime(european_date) # => "31/12/05" four_digit_year_date = '%m/ %d/ %Y' time.strftime(four_digit_year_date) # => "12/31/2005" date_and_time = '%m- %d- %Y %H: %M: %S %Z' time.strftime(date_and_time) # => "12-31-2005 13:22:33 GMT" twelve_hour_clock_time = '%m- %d- %Y %I:%M:%S %p' time.strftime(twelve_hour_clock_time) # => "12-31-2005 01:22:33 PM" word_date = '%A, %B %d, %Y' time.strftime(word_date) # => "Saturday, December 31, 2005"
解説
印刷用紙、パーサー、ユーザーは、日付のフォーマットに非常にうるさいことがある。日付を標準フォーマットで表すと読みやすくなるし、エラーを発見しやすい。フォーマットを1つに決めるを、あいまいさ(4/12は12月4日か、それとも4月12日か)もなくなる。
require 'time'を実行すると、Timeオブジェクトで一般的な日付表示標準のための特殊なフォーマットメソッド(Time#rfc822、Time#httpdate、Time#iso8601)を使用できるようになる。これらのメソッドを使用すれば、電子メール、HTTP、XML企画に準拠したフォーマットで日付を簡単に出力できる。
require 'time' time.rfc822 # => "Sat, 31 Dec 2005 13:22:33:-0000" time.httpdate # => "Sat, 31 Dec 2005 13:22:33:GMT" time.iso8601 # => "2005-12-31T13:22:33Z"
DateTimeは、これら3つのフォーマットのうち、1つだけを提供する。ISO8601は、DateTimeオブジェクトのデフォルトの文字列表現(#to_sの呼び出しによって得られるもの)である。つまり、DateTimeオブジェクトをTimeオブジェクトにわざわざ変換しなくても、XMLドキュメントに簡単に出力できる。
他の2つのフォーマットについては、DateTimeオブジェクトをTimeオブジェクトに変換するのが得策である(詳細については、レシピ1.9を参照)。RFC822とHTTPの日付は、過去または未来のそう遠くない日付に使用されることがほとんどなので、32ビットのタイムカウンタを搭載したシステム上であっても、DateTimeオブジェクトはTimeオブジェクトによってサポートされる1901~2037年の範囲に収まるだろう。
日付のフォーマットをカスタマイズしなければならない場合もある。Time#strftimeとDate#strftimeは、フォーマット文字列で使用するためのディレクティブを多数定義している。以下の表にそれらを示す。これらのディレクティブは、フォーマット文字列で自由に組み合わせることができる。
これらのディレクティブの中には、他のプログラミング言語でもおなじみのものがあるかもしれない。C以降の保母全ての言語に、これらのディレクティブの一部を使用するstrftime実装が含まれている。ディレクティブの中にはRuby独自のものもある。
必要なフォーマットに対応するフォーマットディレクティブがない場合は、Rubyコードを書いて対処しなければならない。たとえば、例の日付を「The 31st of December」のようにフォーマットしたいとしよう。日を序数として出力するための特別なフォーマット文字列はないが、Rubyコードを使用して、正しい答えが得られるフォーマット文字列を組み立てることが出来る。
class Time def day_ordinal_suffix if day == 11 or day == 12 return "th" else case day %10 when 1 then return "st" when 2 then return "nd" when 3 then return "rd" else return "th" end end end end time .strftime("The %e#{time.day_ordinal_suffix} of %B") # => "The 31st of December"
実際のフォーマット文字列は日ウケによって異なる。この場合は、"The %est of %B"という結果が得られるが、その他の日付では、"The %end of %B"、"The %est of %B"、"The %eth of %B"のいずれかになる。
参照
・Timeオブジェクトでは、一般的な日付フォーマットを解析し、それらを出力することが出来る。strftime、httpdate、iso8661の出力を解析する方法については、レシピ1.2を参照のこと。
・レシピ1.11