计算 ruby 中一个月的十分之一的时间距离

Calculate distance of time in tenth of a month in ruby

我正在尝试计算 Ruby 中两个日期之间经过的时间(以月为单位),以十分之一月为单位。因此,例如,从 2015 年 1 月 1 日到 2015 年 2 月 14 日的时间为 1.5 个月。

我发现了这个:

((date2.to_time - date1.to_time)/1.month.second).round(1)

这很好,但这是假设一个月有 30 天 (1.month==30.days)。但显然并非所有月份都是 30 天。我正在寻找一个可以解释不同月份长度的公式。

如果我没看错的话,你正在找这样的东西:

require 'date'

def last_day_of_month(date)
  (((date - date.day + 1) >> 1) - 1).day
end

def diff_in_months(date1, date2, precision=1)
  if date2 < date1
    return -diff_in_months(date2, date1, precision)
  end

  days_month_1 = last_day_of_month(date1)
  ratio1 = (days_month_1 - date1.day + 1) / days_month_1.to_f

  days_month_2 = last_day_of_month(date2)
  ratio2 = date2.day / days_month_2.to_f

  months_diff = (date2.year - date1.year) * 12 +
                date2.month - date1.month - 1

  (ratio1 + ratio2 + months_diff).round(precision)
end

date1 = Date.new(2015,  1,  1)
date2 = Date.new(2015,  2, 14)
date3 = Date.new(2015,  3, 14)
date4 = Date.new(2015,  4,  1)
date5 = Date.new(2016,  1,  1)
date6 = Date.new(2016,  2, 14)

diff_in_months(date1, date2)     # 1.5
diff_in_months(date2, date1, 2)  # -1.5
diff_in_months(date1, date3, 2)  # 2.45
diff_in_months(date4, date4, 2)  # 0.03 (1 day in 30)
diff_in_months(date5, date6, 2)  # 1.48 (Feb'16 has 29 days)

我的解决方案,有 monkey patchingDate class

require 'date'

class Date
  COMMON_YEAR_DAYS_IN_MONTH = [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

  def days_in_month
   return 29 if month == 2 && Date.gregorian_leap?(year)
   COMMON_YEAR_DAYS_IN_MONTH[month]
  end

  def elapsed_month
    ((day.to_f/days_in_month.to_f))
  end

  def remaining_month
    (1.0 - elapsed_month)
  end

  def diff_percent(d)
    from, to = self > d ? [d, self] : [self, d]
    to.elapsed_month + from.remaining_month + (to.month - from.month) - 1
  end

end

from = Date.new(2015, 1, 1)
to = Date.new(2015, 8, 12)

p to.diff_percent(from).round(1) # Prints 7.4
p from.diff_percent(to).round(1) # Prints 7.4