我将构造一个relative_time
有两个参数的方法:
date_time
DateTime的一个实例,它指定过去的时间;和
time_unit
, :SECONDS
, :MINUTES
, :HOURS
, :DAYS
, :WEEKS
,:MONTHS
或之一:YEARS
,指定时间单位,在该时间单位中,当前时间与date_time
要表示的时间差。
代码
require 'date'
TIME_UNIT_TO_SECS = { SECONDS:1, MINUTES:60, HOURS:3600, DAYS:24*3600,
WEEKS: 7*24*3600 }
TIME_UNIT_LBLS = { SECONDS:"seconds", MINUTES:"minutes", HOURS:"hours",
DAYS:"days", WEEKS: "weeks", MONTHS:"months",
YEARS: "years" }
def relative_time(date_time, time_unit)
now = DateTime.now
raise ArgumentError, "'date_time' cannot be in the future" if
date_time > now
v = case time_unit
when :SECONDS, :MINUTES, :HOURS, :DAYS, :WEEKS
(now.to_time.to_i-date_time.to_time.to_i)/
TIME_UNIT_TO_SECS[time_unit]
when :MONTHS
0.step.find { |n| (date_time >> n) > now } -1
when :YEARS
0.step.find { |n| (date_time >> 12*n) > now } -1
else
raise ArgumentError, "Invalid value for 'time_unit'"
end
puts "#{v} #{TIME_UNIT_LBLS[time_unit]} ago"
end
例子
date_time = DateTime.parse("2020-5-20")
relative_time(date_time, :SECONDS)
5870901 seconds ago
relative_time(date_time, :MINUTES)
97848 minutes ago
relative_time(date_time, :HOURS)
1630 hours ago
relative_time(date_time, :DAYS)
67 days ago
relative_time(date_time, :WEEKS)
9 weeks ago
relative_time(date_time, :MONTHS)
2 months ago
relative_time(date_time, :YEARS)
0 years ago
解释
如果time_unit
等于:SECONDS
, :MINUTES
, :HOURS
,:DAYS
或:WEEKS
I 只需计算与当前时间之间经过的秒数date_time
,然后将其除以给定时间单位的秒数。例如,如果time_unit
等于:DAYS
以秒为单位的经过时间除以24*3600
,因为每天有那么多秒。
如果time_unit
等于:MONTHS
,我使用Date#>>方法(由 继承DateTime
)来确定从date_time
达到当前时间之后的时间所经过的月数,然后减去1
。
time_unit
如果等于,则计算类似:YEARS
:确定从date_time
达到当前时间之后的时间所经过的年数,然后减去1
。
可以要求用户输入Time实例(而不是DateTime
实例)作为第一个参数。但是,这不会简化方法,因为Time
实例必须在等于或DateTime
时转换为实例才能使用方法。time_unit
:MONTH
:YEAR
Date#>>