寻找使用Ruby检测生日范围的有效方法

时间:2015-10-30 03:02:20

标签: ruby date sinatra

目前正在开发一款应用程序,该应用程序需要向运营商显示过去7天或接下来21天内生日的员工列表。

我们有一个包含出生日期的人员数据库,按日期范围选择它们相当简单。但是,我们必须显示未来/过去生日的天数是从今天开始的。

代码目前看起来像:

today = Date.today
dob = staff.dob

days = Date.new(today.year, dob.month, dob.day) - today

if days < 0
    "#{ days.abs } days ago"
else
    "in #{ days } days"
end

这几乎适用于所有情况,除了到12月底或1月初。因为我们使用today.year作为年份比较器,如果未来21天溢出到新的一年,我会得到错误的“几天前”读数。 e.g。

今天的日期是20th December 2015,工作人员的生日是2nd January,而不是"in 13 days",我得到"352 days ago"

我知道我可以将代码包装在另一个if / then / else子句中,以检查当前日期是否在12月10日之后,以满足此边缘情况,但日期范围可能会动态更改,而且,代码开始看起来凌乱而且不优雅 - 不像我想要看看ruby代码。

有没有人对如何处理这个问题有更好的建议?

(注意:这是基于Sinatra的项目,所以我没有所有基于ActiveSupport或Rails的魔法,虽然我不反对使用gem,如果它能得到我需要的结果。)

2 个答案:

答案 0 :(得分:2)

require 'date'

class BirthDates
  attr_reader :year, :month, :day
  def initialize(year, month, day)
    @year  = year
    @month = month
    @day   = day
  end
end

def count_days(dob)
  today = Date.today
  this_year = today.year
  days = [this_year-1, this_year, this_year+1].map { |year|
    (Date.new(year, dob.month, dob.day) - today) }.min_by(&:abs)
  if days < 0
    "#{ -days } days ago"
  elsif days > 0
    "in #{ days } days"
  else
   "Happy Birthday!"
  end
end

让我们试一试。 (今天是10月29日)

dob = BirthDates.new(1908, 12, 28)
count_days(dob) #=> "in 60 days"

dob = BirthDates.new(1999, 10, 27)
count_days(dob) #=> "2 days ago"

dob = BirthDates.new(2014, 10, 29)
count_days(dob) #=> "Happy Birthday"

如果今天是1月5日:

dob = BirthDates.new(1908, 12, 28)
count_days(dob) #=> "8 days ago"

dob = BirthDates.new(1999, 3, 27)
count_days(dob) #=> "in 82 days"

答案 1 :(得分:1)

获得今年,明年和去年的最小日子

today = Date.today
dob = staff.dob

this_dob = Date.new(today.year, dob.month, dob.day)
next_dob = this_dob.next_year
prev_dob = this_dob.prev_year
days = [this_dob - today, next_dob - today, prev_dob - today].min_by{|i| i.to_i.abs}

if days < 0
  "#{ days.abs } days ago"
else
  "in #{ days } days"
end