ActiveSupport::CoreExtensions::Date::Conversions

勉強会でちょっと話題となっていたActiveSupport黒魔術、できる限りでちょっとずつ解説をしていきたいと思います。Rails 1.0を対象ということで。

追記2006/03/22

すでにid:secondlifeさんのwiki.rails2u.comのactivesupportタグにかなり情報がまとまってますね。ということで今後はそちらを見ましょう。
私もなんか気づいたら書き込んでいきたいと思います。

本日はActiveSupport::CoreExtensions::Date::ConversionsでのDateクラスへの拡張です。

Date#to_date

selfを返します。次に述べるto_timeと組み合わせることで、DateとTimeどっちでもいいような処理をポリモルフィックに記述できます。

Date#to_time(form = :local)

自身の年、月、日を用いてTimeクラスのインスタンスを生成し、返します。第一引数を省略すると現在のタイムゾーンで(Time.localが呼びされる)、:utcを指定することでUTCで生成されます(Time.utc()が呼ばれる)。

これらの使いかたとして、以下のような処理をしたいときに場合分けを考えな意で、一気にかけて染まします。

ある時

  def print_start_day(date_or_time)
    # Time#jdは定義されていない。Date型に対してユリウス日を返すメソッド。
    puts date_or_time.to_date.jd
  end

  def print_beginning_of_month(date_or_time)
    # at_beginning_of_monthはActiveSupportにTimeのみで追加されるメソッド。月頭を返す。
    puts date_or_time.to_time.at_beginning_of_month
  end

ない時
結局のところ、自前で名が井上に別に難しくはないという処理を書かなきゃいけなくなります。(実際、ActiveSupport::CoreExtensions::Date::Conversions内で定義されているの処理はほぼ↓と同じです)

  def print_beginning_of_month(date_or_time)
    if date_or_time.is_a? Date
      date_or_time = Time.local(date_or_time.year,date_or_time.month,date_or_time.day)
    end
    puts date_or_time.to_time.at_beginning_of_month
  end

to_procを含め、既に変更後にマッチしていればselfを、そうでなければ変換結果を呼び出す、というメソッドが定義されていると、Ducktypeのうれしさがいっそう増しますね。

to_formatted_s(format = :default)

あらかじめ指定されたフォーマットに従いDateをフォーマットした文字列を返します。また、このメソッドはDate#to_sへエイリアスされるため、to_sで呼び出すことができるようになります。
それ以前のto_sはto_default_sで呼び出すことができます。

ちなみに、新規で定義されるフォーマットは以下の2通りです。

  DATE_FORMATS = {
    :short => "%e %b",
    :long  => "%B %e, %Y"
  }

これにさらにフォーマットを追加することももちろんできます。指定方法はちょっと失念してしまったので誰かフォローしてくれるとありがたいです。Rails本に載っていたと思うんですけど。。。

2006/03/22追記

secondlifeさんのwikiにフォーマットの追加方法がありました。

  ::ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS.update :ore => "%Y::%m::%d %H_%M_%S"

DATE_FORMATSは普通のHashですので、上記の方法で追加できます。Timeのフォーマットも同様です。