8
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

Organization

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

ある期間の開始日時が分かっていて、現在まで何年何ヶ月以上経過しているのかの差分を取って欲しい、みたいな要件が 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。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
8
Help us understand the problem. What are the problem?