6
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

日付の差分を「○年△ヶ月」で取得する in Rails

Posted at

ある期間の開始日時が分かっていて、現在まで何年何ヶ月以上経過しているのかの差分を取って欲しい、みたいな要件が Rails でありました。

はじめに考えた

Rails にはdistance_of_time_in_words_to_nowというまさになヘルパーメソッドがあるのでそれの利用を検討したんですが、このメソッドは「1分」「3分」「5分」みたいに近い時間は細かく扱ってくれるけど、期間が長くなると「約1ヶ月」「約2年」みたいに結構マルっと丸めてくれるので用途に合いませんでした。ということで自前で実装することにしました。

日付の差分を「○年△ヶ月」で取得する

  def distance_of_time_in_words_to_now(from_time)
    distance_of_time_in_words(from_time, Time.now)
  end

  def distance_of_time_in_words(from_time, to_time)
    from_time = from_time.to_date if from_time.respond_to?(:to_date)
    to_time = to_time.to_date if to_time.respond_to?(:to_date)
    years = 0
    months = 0
    loop {
      from = from_time + years.year + months.month
      if    (to_time - (from + 1.year))  >= 0 then years  += 1
      elsif (to_time - (from + 1.month)) >= 0 then months += 1
      else break
      end
    }
    distance = ''
    distance += "#{years}年 " if years != 0
    distance += "#{months}ヶ月"
  end

from を「1年」or「1ヶ月」ずつズラしていって「○年△ヶ月」を計算するようにしました。もう少し書き足せば「○年△ヶ月□日」とかもイケそうですね。

まとめ

こういうときの悩みどころは「1年」や「1ヶ月」の扱いだと思います。「1年 = 366日」の年もあれば「1ヶ月 = 28日」の月もあるわけで、どうやってその辺をうまく「1年」「1ヶ月」として扱うかということ。
自前で「?年?月だからこの月は 28日」とか「?年だから 366日」とか実装することを考えると・・・いや考えたくないですね。今回は ActiveSupport にその辺を任せることでうまく実装できました。ありがとう ActiveSupport。

6
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?