Class: Runby::RunbyTime

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/runby_pace/runby_time.rb

Overview

Represents a human-readable time in the format MM:ss

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(time) ⇒ RunbyTime

Returns a new instance of RunbyTime.



8
9
10
11
12
13
14
15
16
# File 'lib/runby_pace/runby_time.rb', line 8

def initialize(time)
  if time.is_a?(String) || time.is_a?(Symbol)
    init_from_string time
  elsif time.is_a?(RunbyTime)
    init_from_clone time
  elsif time.is_a?(Hash)
    init_from_hash time
  end
end

Instance Attribute Details

#minutes_partObject (readonly)

Returns the value of attribute minutes_part.



6
7
8
# File 'lib/runby_pace/runby_time.rb', line 6

def minutes_part
  @minutes_part
end

#seconds_partObject (readonly)

Returns the value of attribute seconds_part.



6
7
8
# File 'lib/runby_pace/runby_time.rb', line 6

def seconds_part
  @seconds_part
end

#time_sObject (readonly)

Returns the value of attribute time_s.



6
7
8
# File 'lib/runby_pace/runby_time.rb', line 6

def time_s
  @time_s
end

Class Method Details

.from_minutes(total_minutes) ⇒ Object

Parameters:

  • total_minutes (numeric)


26
27
28
# File 'lib/runby_pace/runby_time.rb', line 26

def self.from_minutes(total_minutes)
  from_seconds(total_minutes * 60.0)
end

.from_seconds(total_seconds) ⇒ Object

Parameters:

  • total_seconds (numeric)


19
20
21
22
23
# File 'lib/runby_pace/runby_time.rb', line 19

def self.from_seconds(total_seconds)
  minutes = total_seconds.abs.to_i / 60
  seconds = total_seconds.abs.to_i % 60
  RunbyTime.new format('%02d:%02d', minutes, seconds)
end

.parse(str) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/runby_pace/runby_time.rb', line 30

def self.parse(str)
  time = str.to_s.strip.chomp

  if time.match(/^\d?\d:\d\d$/)
    parts = time.split(':')
    minutes_part = parts[0].to_i
    seconds_part = parts[1].to_i
  elsif time.match(/^\d+$/)
    minutes_part = time.to_i
    seconds_part = 0
  elsif time.match(/^\d+[,. ]\d+$/)
    parts = time.split(/[,. ]/)
    minutes_part = parts[0].to_i
    seconds_part = (parts[1].to_i / 10.0 * 60).to_i
  else
    raise 'Invalid time format'
  end

  raise 'Minutes must be less than 100' if minutes_part > 99
  raise 'Seconds must be less than 60' if seconds_part > 59
  time_formatted = "#{minutes_part.to_s.rjust(2, '0')}:#{seconds_part.to_s.rjust(2, '0')}"

  RunbyTime.new(time_s: time_formatted, minutes_part: minutes_part, seconds_part: seconds_part)
end

.try_parse(str, is_five_k = false) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/runby_pace/runby_time.rb', line 55

def self.try_parse(str, is_five_k = false)
  time, error_message, warning_message = nil
  begin
    time = parse str
  rescue StandardError => ex
    error_message = "#{ex.message} (#{str})"
  end

  # Break out these sanity checks into their own class if we add any more.
  if !time.nil? && is_five_k
    warning_message = '5K times of less than 14:00 are unlikely' if time.minutes_part < 14
    warning_message = '5K times of greater than 42:00 are not fully supported' if time.total_seconds > (42 * 60)
  end

  { time: time, error: error_message, warning: warning_message }
end

Instance Method Details

#+(other) ⇒ Object

Parameters:



92
93
94
95
96
# File 'lib/runby_pace/runby_time.rb', line 92

def +(other)
  if other.is_a?(RunbyTime)
    RunbyTime.from_seconds(total_seconds + other.total_seconds)
  end
end

#-(other) ⇒ Object

Parameters:



85
86
87
88
89
# File 'lib/runby_pace/runby_time.rb', line 85

def -(other)
  if other.is_a?(RunbyTime)
    RunbyTime.from_seconds(total_seconds - other.total_seconds)
  end
end

#<=>(other) ⇒ Object



98
99
100
101
102
103
104
105
# File 'lib/runby_pace/runby_time.rb', line 98

def <=>(other)
  if other.is_a? RunbyTime
    total_seconds <=> other.total_seconds
  elsif other.is_a? String
    return 0 if @time_s == other
    total_seconds <=> parse(other).total_seconds
  end
end

#almost_equals?(other_time, tolerance_time = '00:01') ⇒ Boolean

Returns:

  • (Boolean)


107
108
109
110
111
112
113
# File 'lib/runby_pace/runby_time.rb', line 107

def almost_equals?(other_time, tolerance_time = '00:01')
  if other_time.is_a?(String)
    other_time = RunbyTime.new(other_time)
  end
  tolerance = RunbyTime.new(tolerance_time)
  self >= (other_time - tolerance) && self <= (other_time + tolerance)
end

#to_sObject



72
73
74
# File 'lib/runby_pace/runby_time.rb', line 72

def to_s
  @time_s.sub(/^[0:]*/, '')
end

#total_minutesObject



80
81
82
# File 'lib/runby_pace/runby_time.rb', line 80

def total_minutes
  @minutes_part + (@seconds_part / 60.0)
end

#total_secondsObject



76
77
78
# File 'lib/runby_pace/runby_time.rb', line 76

def total_seconds
  @minutes_part * 60 + @seconds_part
end