Class: Duration

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/duration.rb,
lib/duration/version.rb

Overview

Duration objects are simple mechanisms that allow you to operate on durations of time. They allow you to know how much time has passed since a certain point in time, or they can tell you how much time something is (when given as seconds) in different units of time measurement. Durations would particularly be useful for those scripts or applications that allow you to know the uptime of themselves or perhaps provide a countdown until a certain event.

Direct Known Subclasses

Days, Decades, Hours, Minutes, Months, Seconds, Weeks, Years

Constant Summary collapse

UNITS =
[:seconds, :minutes, :hours, :days, :weeks, :months, :years]
MULTIPLES =
{:seconds => 1,
:minutes => 60,
:hours   => 3600,
:days    => 86400,
:weeks   => 604800,
:months  => 2592000, # 30 days
:years   => 31557600, # 365.25 days
:second  => 1,
:minute  => 60,
:hour    => 3600,
:day     => 86400,
:week    => 604800,
:month   => 2592000,
:year    => 31557600}
VERSION =
"3.0.0"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args = 0) ⇒ Duration

Initialize a duration. ‘args’ can be a hash or anything else. If a hash is passed, it will be scanned for a key=>value pair of time units such as those listed in the Duration::UNITS array or Duration::MULTIPLES hash.

If anything else except a hash is passed, #to_i is invoked on that object and expects that it return the number of seconds desired for the duration.



43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/duration.rb', line 43

def initialize(args = 0)
  if args.kind_of?(Hash)
    @seconds = 0
    MULTIPLES.each do |unit, multiple|
      unit = unit.to_sym
      @seconds += args[unit].to_i * multiple if args.key?(unit)
    end
  else
    @seconds = args.to_i
  end

  calculate!
end

Instance Attribute Details

#daysObject (readonly)

Returns the value of attribute days.



35
36
37
# File 'lib/duration.rb', line 35

def days
  @days
end

#hoursObject (readonly)

Returns the value of attribute hours.



35
36
37
# File 'lib/duration.rb', line 35

def hours
  @hours
end

#minutesObject (readonly)

Returns the value of attribute minutes.



35
36
37
# File 'lib/duration.rb', line 35

def minutes
  @minutes
end

#monthsObject (readonly)

Returns the value of attribute months.



35
36
37
# File 'lib/duration.rb', line 35

def months
  @months
end

#secondsObject (readonly)

Returns the value of attribute seconds.



35
36
37
# File 'lib/duration.rb', line 35

def seconds
  @seconds
end

#totalObject (readonly) Also known as: to_i

Returns the value of attribute total.



35
36
37
# File 'lib/duration.rb', line 35

def total
  @total
end

#weeksObject (readonly)

Returns the value of attribute weeks.



35
36
37
# File 'lib/duration.rb', line 35

def weeks
  @weeks
end

#yearsObject (readonly)

Returns the value of attribute years.



35
36
37
# File 'lib/duration.rb', line 35

def years
  @years
end

Instance Method Details

#%(other) ⇒ Object



79
80
81
# File 'lib/duration.rb', line 79

def %(other)
  Duration.new(@total % other.to_i)
end

#*(other) ⇒ Object



71
72
73
# File 'lib/duration.rb', line 71

def *(other)
  Duration.new(@total * other.to_i)
end

#+(other) ⇒ Object



63
64
65
# File 'lib/duration.rb', line 63

def +(other)
  Duration.new(@total + other.to_i)
end

#-(other) ⇒ Object



67
68
69
# File 'lib/duration.rb', line 67

def -(other)
  Duration.new(@total - other.to_i)
end

#/(other) ⇒ Object



75
76
77
# File 'lib/duration.rb', line 75

def /(other)
  Duration.new(@total / other.to_i)
end

#<=>(other) ⇒ Object

Compare this duration to another (or objects that respond to #to_i)



58
59
60
61
# File 'lib/duration.rb', line 58

def <=>(other)
  return false unless other.is_a?(Duration)
  @total <=> other.to_i
end

#blank?Boolean

Returns true if total is 0.

Returns:

  • (Boolean)

    true if total is 0



107
108
109
# File 'lib/duration.rb', line 107

def blank?
  @total == 0
end

#format(format_str) ⇒ Object Also known as: strftime

Format a duration into a human-readable string.

%w   => weeks
%d   => days
%h   => hours
%m   => minutes
%s   => seconds
%td  => total days
%th  => total hours
%tm  => total minutes
%ts  => total seconds
%t   => total seconds
%H   => zero-padded hours
%M   => zero-padded minutes
%S   => zero-padded seconds
%~s  => locale-dependent "seconds" terminology
%~m  => locale-dependent "minutes" terminology
%~h  => locale-dependent "hours" terminology
%~d  => locale-dependent "days" terminology
%~w  => locale-dependent "weeks" terminology
%tdu => total days with locale-dependent unit
%thu => total hours with locale-dependent unit
%tmu => total minutes with locale-dependent unit
%tsu => total seconds with locale-dependent unit

You can also use the I18n support. The %~s, %~m, %~h, %~d and %~w can be translated with I18n. If you are using Ruby on Rails, the support is ready out of the box, so just change your locale file. Otherwise you can try:

I18n.load_path << "path/to/your/locale"
I18n.locale = :your_locale

And you must use the following structure (example) for your locale file:

pt:
  ruby_duration:
    second: segundo
    seconds: segundos
    minute: minuto
    minutes: minutos
    hour: hora
    hours: horas
    day: dia
    days: dias
    week: semana
    weeks: semanas


162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/duration.rb', line 162

def format(format_str)
  identifiers = {
    'y'  => @years,
    'o'  => @months,
    'w'  => @weeks,
    'd'  => @days,
    'h'  => @hours,
    'm'  => @minutes,
    's'  => @seconds,
    'ty' => Proc.new { total_years },
    'to' => Proc.new { total_months },
    'tw' => Proc.new { total_weeks },
    'td' => Proc.new { total_days },
    'th' => Proc.new { total_hours },
    'tm' => Proc.new { total_minutes },
    'ts' => @total,
    't'  => @total,
    'H'  => @hours.to_s.rjust(2, '0'),
    'M'  => @minutes.to_s.rjust(2, '0'),
    'S'  => @seconds.to_s.rjust(2, '0'),
    '~s' => i18n_for(:second),
    '~m' => i18n_for(:minute),
    '~h' => i18n_for(:hour),
    '~d' => i18n_for(:day),
    '~w' => i18n_for(:week),
    '~o' => i18n_for(:month),
    '~y' => i18n_for(:year),
    'tyr'=> Proc.new { "#{total_years} #{i18n_for(:total_year)}"},
    'tmo'=> Proc.new { "#{total_months} #{i18n_for(:total_month)}"},
    'twk'=> Proc.new { "#{total_weeks} #{i18n_for(:total_week)}"},
    'tdu'=> Proc.new { "#{total_days} #{i18n_for(:total_day)}"},
    'thu'=> Proc.new { "#{total_hours} #{i18n_for(:total_hour)}"},
    'tmu'=> Proc.new { "#{total_minutes} #{i18n_for(:total_minute)}"},
    'tsu'=> Proc.new { "#{total} #{i18n_for(:total)}"}
  }

  format_str.gsub(/%?%(y|o|w|d|h|m|s|t([ydhms]u?)?|H|M|S|~(?:s|m|h|d|w|o|y))/) do |match|
    match['%%'] ? match : (identifiers[match[1..-1]].class == Proc ? identifiers[match[1..-1]].call : identifiers[match[1..-1]])
  end.gsub('%%', '%')
end

#iso8601Object

Formats a duration in ISO8601.



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/duration.rb', line 89

def iso8601
  output = 'P'

  output << "#{years}Y" if years > 0
  output << "#{months}M" if months > 0
  output << "#{weeks}W" if weeks > 0
  output << "#{days}D" if days > 0
  if seconds > 0 || minutes > 0 || hours > 0
    output << 'T'
    output << "#{hours}H" if hours > 0
    output << "#{minutes}M" if minutes > 0
    output << "#{seconds}S" if seconds > 0
  end

  output
end

#present?Boolean

Returns true if total different than 0.

Returns:

  • (Boolean)

    true if total different than 0



112
113
114
# File 'lib/duration.rb', line 112

def present?
  !blank?
end