neocities/ext/ago.rb
2017-04-02 13:58:32 -07:00

170 lines
4.4 KiB
Ruby

module Ago
module VERSION
MAJOR = 0
MINOR = 1
TINY = 5
class << self
def pretty
"#{MAJOR}.#{MINOR}.#{TINY}"
end
alias_method :print, :pretty
end
end
Ago::Order = [:year, :month, :week, :day, :hour, :minute, :second]
Ago::Units = {
:year => {
:basic => 60 * 60 * 24 * 365,
:gregorian => 86400 * 365.2425,
},
:month => {
:basic => 60 * 60 * 24 * 30,
:gregorian => 86400 * 30.436875,
},
:week => {
:basic => 60 * 60 * 24 * 7,
:gregorian => 86400 * 7.02389423076923,
},
:day => {
:basic => 60 * 60 * 24
},
:hour => {
:basic => 60 * 60
},
:minute => {
:basic => 60
},
:second => {
:basic => 1
}
}
def Ago.calendar_check(calendar)
error = ":calendar => value must be either :basic or :gregorian."
unless calendar == :basic || calendar == :gregorian
raise ArgumentError, error
end
end
module Ago::TimeAgo
# Generate List of valid unit :symbols
valids = ""
Ago::Order.each do |u|
unless u == :second
valids += ":#{u.to_s}, "
else
valids += "and :#{u.to_s}."
end
end
Valids = valids
def ago_in_words(opts={})
# Process options {hash}
focus = opts[:focus] ? opts[:focus] : 0
start_at = opts[:start_at] ? opts[:start_at] : :year
now = opts[:now] ? opts[:now] : Time.now
in_time = opts[:in_time] ? opts[:in_time] : :past
calendar = opts[:calendar] ? opts[:calendar] : :basic
# Filter out invalid arguments for :in_time
in_time_error = ":in_time => value must be either :past or :future, " \
+ "depending on whether the Time object is before or after Time.now."
unless in_time == :past || in_time == :future
raise ArgumentError, in_time_error
end
# Filter out invalid arguments for :calendar
Ago.calendar_check(calendar)
# Filter out invalid arguments for :start_at and :focus
base_error = " => value must either be a number " +
"between 0 and 6 (inclusive),\nor one of the following " +
"symbols: " + Valids
{:focus => focus, :start_at => start_at}.each do |key, opt|
opt_error = ":" + key.to_s + base_error
if opt.class == Integer
raise ArgumentError, opt_error unless opt >= 0 && opt <= 6
elsif opt.class == Symbol
raise ArgumentError, opt_error unless Ago::Units[opt]
else
raise ArgumentError, opt_error
end
end
# Create Variables necessary for processing.
frags = []
output = ""
count = 0
now = calendar == :basic ? now.to_i : now.to_f
my_time = calendar == :basic ? self.to_i : self.to_f
if now > my_time
diff = now - my_time
tail = " ago"
elsif my_time > now
diff = my_time - now
tail = " from now"
else
diff = 0
tail = "just now"
end
# Begin Ago.ago processing
Ago::Order.each do |u|
if calendar == :gregorian && Ago::Units[u][:gregorian]
value = Ago::Units[u][:gregorian]
else
value = Ago::Units[u][:basic]
end
count += 1
# Move further ahead in the Ago::Units array if start_at is farther back than
# the current point in the array.
if start_at.class == Integer
next if count <= start_at
elsif start_at.class == Symbol
next if Ago::Order.index(u) < Ago::Order.index(start_at)
end
n = (diff/value).floor
if n > 0
plural = n > 1 ? "s" : ""
frags << "#{n} #{u.to_s + plural}"
# If the argument passed into ago() is a symbol, focus the ago statement
# down to the level specified in the symbol
puts focus.class.inspect
if focus.class == Symbol
break if u == focus || u == :second
elsif focus.class == Integer
if focus == 0 || u == :second
break
else
focus -= 1
end
end
diff -= n * value
end
end
# Der Kommissar
frags.size.times do |n|
output += frags[n]
output += ", " unless n == frags.size - 1
end
return output + "#{tail}"
end
def from_now_in_words(opts={})
ago_in_words(opts)
end
end
end
class Time
include Ago::TimeAgo
end