我在生日小工具上工作,显示最接近他生日的人的姓名。
我目前有以下代码;
<%
def closest_birthdate(birthdates)
sorted_dates = birthdates.sort_by do |_, value|
(DateTime.parse(value) - DateTime.now).abs
end
name, birthday = sorted_dates.first
"#{name} has his birthday on #{Date.parse(birthday).strftime('%m-%d')}"
end
%>
<% hash = { 'Bart' => '2017-12-06',
'Thomas' => '2017-10-06',
'William' => '2018-09-05',} %>
<%= closest_birthdate(hash) %>
返回以下内容:
Thomas has his birthday on 10-06
现在,在他生日那天之后,我必须将年份从2017年改为2018年。 名称日期目前存储为字符串。
答案 0 :(得分:0)
没有标准对象作为(出生)日没有指定年份。所以你应该只保存月份和月份的数组。将它们保存为整数而不是字符串要好得多。
hash = {
'Bart' => [12, 6],
'Thomas' => [10, 6],
'William' => [9, 5],
}
要将它们转换为具有年份规格的日期(假设为year = 2018
),请执行以下操作:
require "date"
date = Date.new(year, *hash['Bart']) rescue nil
完全实现它将是这样的:
require "date"
def closest_birthdate(birthdates)
year, month, day = Date.today.year, Date.today.month, Date.today.day
name, (m, d) =
birthdates
.sort_by(&:last)
.bsearch{|_, (m, d)| month <= m and day < d}
return unless Date.new(year, m, d) rescue nil
"#{name} has his birthday on #{year}-#{m}-#{d}"
end
closest_birthdate(hash)
答案 1 :(得分:0)
如果您不想更改结构,请尝试此操作:
<%
def closest_birthdate(birthdates)
sorted_dates = birthdates.sort_by do |_, value|
array = value.split("-") # you got something like this [2017, 12, 06]
(DateTime.parse("#{DateTime.now.year}-#{array[1]}-#{array[2]}") - DateTime.now).abs
end
name, birthday = sorted_dates.first
"#{name} has his birthday on #{Date.parse(birthday).strftime('%m-%d')}"
end
%>
<% hash = { 'Bart' => '1978-12-06',
'Thomas' => '1972-10-06',
'William' => '1992-09-05',} %>
<%= closest_birthdate(hash) %>
希望这有帮助。
答案 2 :(得分:0)
require 'date'
birthdate = Date.new(1978, 12, 6)
#=> #<Date: 1978-12-06 ...>
上述生日的下一个或即将到来的生日是2017-12-06,所以我们必须将今天和出生日期的月份和日期结合起来:
today = Date.today
#=> #<Date: 2017-10-06 ...>
next_birthday = Date.new(today.year, birthdate.month, birthdate.day)
#=> #<Date: 2017-12-06 ...>
如果生日已经在今年发生,会发生什么?
birthdate = Date.new(1985, 9, 5)
#=> #<Date: 1985-12-06 ...>
next_birthday = Date.new(today.year, birthdate.month, birthdate.day)
#=> #<Date: 2017-09-05 ...>
要实际获得下一个生日,我们必须在这种情况下添加一年:(即如果next_birthday
恰好在今天之前)
next_birthday = next_birthday.next_year if next_birthday < today
#=> #<Date: 2018-09-05 ...>
让我们将上述计算转移到一个方法中:
def next_birthday(birthdate, today = Date.today)
date = Date.new(today.year, birthdate.month, birthdate.day)
date < today ? date.next_year : date
end
要查找最近(即将到来)的生日,我们可以使用sort_by
和first
:
hash = {
'Bart' => Date.new(1978, 12, 6),
'Thomas' => Date.new(1981, 10, 6),
'William' => Date.new(1985, 9, 5)
}
hash.sort_by { |_name, birthdate| next_birthday(birthdate) }
#=> [
# ["Thomas", #<Date: 1981-10-06 ...>],
# ["Bart", #<Date: 1978-12-06 ...>],
# ["William", #<Date: 1985-09-05 ...>]
# ]
hash.sort_by { |_name, birthdate| next_birthday(birthdate) }.first
#=> ["Thomas", #<Date: 1981-10-06 ...>]
或min_by
:
hash.min_by { |_name, birthdate| next_birthday(birthdate) }
#=> ["Thomas", #<Date: 1981-10-06 ...>]
name, birthdate = hash.min_by { |_name, birthdate| next_birthday(birthdate) }
puts "#{name}'s birthday is on #{birthdate.strftime('%m-%d')}"
# Thomas's birthday is on 10-06
我们还可以添加年龄:
age = next_birthday(birthdate).year - birthdate.year
#=> 36
puts "#{name} is turning #{age} on #{birthdate.strftime('%m-%d')}"
# Thomas is turning 36 on 10-06
2月29日仅发生在闰年:
Date.new(1984, 2, 29)
#=> #<Date: 1984-02-29 ...>
尝试在非闰年创建2月29日会导致错误:
Date.new(2017, 2, 29)
#=> ArgumentError: invalid date
除非今天的年份为leap?
(截至2月28日或3月1日),否则您可以删除这些日期或进行调整。