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.

Constant Summary collapse

UNITS =
[:seconds, :minutes, :hours, :days, :weeks]
MULTIPLES =
{:seconds => 1,
:minutes => 60,
:hours   => 3600,
:days    => 86400,
:weeks   => 604800,
:second  => 1,
:minute  => 60,
:hour    => 3600,
:day     => 86400,
:week    => 604800}
VERSION =
"3.2.3".freeze

Instance Attribute Summary collapse

Class Method 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.



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/duration.rb', line 36

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
  elsif args.kind_of?(String) and args[0] == 'P'
    @seconds = ISO8601::Duration.new(args).to_seconds
  else
    @seconds = args.to_i
  end

  calculate!
end

Instance Attribute Details

#daysObject (readonly)

Returns the value of attribute days.



28
29
30
# File 'lib/duration.rb', line 28

def days
  @days
end

#hoursObject (readonly)

Returns the value of attribute hours.



28
29
30
# File 'lib/duration.rb', line 28

def hours
  @hours
end

#minutesObject (readonly)

Returns the value of attribute minutes.



28
29
30
# File 'lib/duration.rb', line 28

def minutes
  @minutes
end

#secondsObject (readonly)

Returns the value of attribute seconds.



28
29
30
# File 'lib/duration.rb', line 28

def seconds
  @seconds
end

#totalObject (readonly) Also known as: to_i

Returns the value of attribute total.



28
29
30
# File 'lib/duration.rb', line 28

def total
  @total
end

#weeksObject (readonly)

Returns the value of attribute weeks.



28
29
30
# File 'lib/duration.rb', line 28

def weeks
  @weeks
end

Class Method Details

.dump(duration) ⇒ Object



56
57
58
# File 'lib/duration.rb', line 56

def self.dump duration
  duration.iso8601
end

.load(string) ⇒ Object



52
53
54
# File 'lib/duration.rb', line 52

def self.load string
  self.new(string)
end

Instance Method Details

#%(other) ⇒ Object



90
91
92
93
94
# File 'lib/duration.rb', line 90

def %(other)
  total = negative? ? -@total : @total
  if other.class == Duration then other = other.negative? ? -other.total : other.total end
  Duration.new(total % other.to_i)
end

#*(other) ⇒ Object



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

def *(other)
  total = negative? ? -@total : @total
  if other.class == Duration then other = other.negative? ? -other.total : other.total end
  Duration.new(total * other.to_i)
end

#+(other) ⇒ Object



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

def +(other)
  total = negative? ? -@total : @total
  if other.class == Duration then other = other.negative? ? -other.total : other.total end
  Duration.new(total + other.to_i)
end

#-(other) ⇒ Object



72
73
74
75
76
# File 'lib/duration.rb', line 72

def -(other)
  total = negative? ? -@total : @total
  if other.class == Duration then other = other.negative? ? -other.total : other.total end
  Duration.new(total - other.to_i)
end

#/(other) ⇒ Object



84
85
86
87
88
# File 'lib/duration.rb', line 84

def /(other)
  total = negative? ? -@total : @total
  if other.class == Duration then other = other.negative? ? -other.total : other.total end
  Duration.new(total / other.to_i)
end

#<=>(other) ⇒ Object

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



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

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



122
123
124
# File 'lib/duration.rb', line 122

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
%MP  => minutes with UTF-8 prime
%SP  => seconds with UTF-8 double-prime
%MH  => minutes with HTML prime
%SH  => seconds with HTML double-prime
%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


185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/duration.rb', line 185

def format(format_str)
  identifiers = {
    'w'  => @weeks,
    'd'  => @days,
    'h'  => @hours,
    'm'  => @minutes,
    's'  => @seconds,
    'td' => Proc.new { total_days },
    'th' => Proc.new { total_hours },
    'tm' => Proc.new { total_minutes },
    'ts' => @total,
    't'  => @total,
    'MP' =>  Proc.new { "#{@minutes}"},
    'SP' =>  Proc.new { "#{@seconds}"},
    'MH' =>  Proc.new { "#{@minutes}&#8242;"},
    'SH' =>  Proc.new { "#{@seconds}&#8243;"},
    '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),
    '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(/%?%(w|d|h|m|s|t([dhms]u?)?|MP|SP|MH|SH|H|M|S|~(?:s|m|h|d|w))/) 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.



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/duration.rb', line 102

def iso8601
  if present?
    output = 'P'

    number_of_days = weeks * 7 + days
    output << "#{number_of_days}D" if number_of_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

    negative? ? "-#{output}" : output
  else
    'PT0S'
  end
end

#negative?Boolean

Returns:

  • (Boolean)


131
132
133
# File 'lib/duration.rb', line 131

def negative?
  @negative
end

#present?Boolean

Returns true if total different than 0.

Returns:

  • (Boolean)

    true if total different than 0



127
128
129
# File 'lib/duration.rb', line 127

def present?
  !blank?
end