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.2".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.



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

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.



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

def days
  @days
end

#hoursObject (readonly)

Returns the value of attribute hours.



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

def hours
  @hours
end

#minutesObject (readonly)

Returns the value of attribute minutes.



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

def minutes
  @minutes
end

#secondsObject (readonly)

Returns the value of attribute seconds.



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

def seconds
  @seconds
end

#totalObject (readonly) Also known as: to_i

Returns the value of attribute total.



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

def total
  @total
end

#weeksObject (readonly)

Returns the value of attribute weeks.



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

def weeks
  @weeks
end

Class Method Details

.dump(duration) ⇒ Object



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

def self.dump duration
  duration.iso8601
end

.load(string) ⇒ Object



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

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

Instance Method Details

#%(other) ⇒ Object



81
82
83
# File 'lib/duration.rb', line 81

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

#*(other) ⇒ Object



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

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

#+(other) ⇒ Object



65
66
67
# File 'lib/duration.rb', line 65

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

#-(other) ⇒ Object



69
70
71
# File 'lib/duration.rb', line 69

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

#/(other) ⇒ Object



77
78
79
# File 'lib/duration.rb', line 77

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

#<=>(other) ⇒ Object

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



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

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



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

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


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
202
203
204
205
206
207
# File 'lib/duration.rb', line 174

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.



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

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)


120
121
122
# File 'lib/duration.rb', line 120

def negative?
  @negative
end

#present?Boolean

Returns true if total different than 0.

Returns:

  • (Boolean)

    true if total different than 0



116
117
118
# File 'lib/duration.rb', line 116

def present?
  !blank?
end