💡

[Misc #21325] `Time#strftime` を `Time#format` という名前で利用したいというチケット

に公開

[Misc #21325] make ruby more middle-aged man friendly

  • タイトルはアレなんですが内容は Time#strftimeTime#format という名前で利用したいというチケット
  • Time#strftime 時刻の情報を任意のフォーマットに変換するようなメソッドですね
time = Time.new(2025, 5, 2)
pp time.strftime("%Y-%m-%d") # => "2025-05-02"
pp time.strftime("%y/%m/%d") # => "25/05/02"
  • そもそもなんですが現状だと Kernel.#format が別に private メソッドとして定義されているんですよねー
    • こっちは Kernel.#sprintf の alias として定義されています
  • なので Time に対して #format は以下のように動作します
class Time
  def hoge
    # これは 1000 の値を %04x というフォーマットで変換しているだけ
    p format("%04x", 1000)
    # => "03e8"
  end
end

Time.now.hoge

# format は private メソッドなので外から呼び出すことはできない
# error private method 'format' called for an instance of String (NoMethodError)
Time.now.format("%04x", 1000)
  • #format はレシーバに依存せず関数ライクな形で利用するみたいな想定ですねー
  • 対応するとすれば Time#format を再定義するのか別の名前で定義するのか、みたいな選択肢になりそう
  • ふと思ったけど『 private メソッドをレシーバ付きで呼び出すと #method_missing が優先して呼ばれる』を利用すると以下ように『 format という名前は同じだがレシーバありとなしで使い分けできる』みたいなことは実現できそう
    • これがいいかどうかは置いといて
class Time
  def method_missing(name, ...)
    if name == :format
      strftime(...)
    else
      super(name, ...)
    end
  end

  def hoge
    # レシーバがない場合は Kernel.#format が呼び出される
    pp format("%04x", 1000) # => "03e8"
  end
end

Time.now.hoge

# レシーバがある場合は method_missing 経由で Time#strftime が呼ばれる
pp Time.now.format("%Y-%m-%d") # => "2025-06-04"
GitHubで編集を提案

Discussion