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


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

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

#*(other) ⇒ Object


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

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

#+(other) ⇒ Object


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

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

#-(other) ⇒ Object


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

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

#/(other) ⇒ Object


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

def /(other)
  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


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

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

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
208
# File 'lib/duration.rb', line 175

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.


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

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)

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

def negative?
  @negative
end

#present?Boolean

Returns true if total different than 0.

Returns:

  • (Boolean)

    true if total different than 0


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

def present?
  !blank?
end