Class: Delay

Inherits:
Object
  • Object
show all
Defined in:
lib/delay.rb

Overview

Delay permits to define explicit and complex delays Delay are not always linears due to BOM/EOM, so if D3 = D1 + D2 is true, D1 = D2 - D3 is not always true.

Defined Under Namespace

Modules: Validation

Constant Summary collapse

SEPARATOR =
','.freeze
TRANSLATIONS =
{
  'an' => :year,
  'ans' => :year,
  'année' => :year,
  'années' => :year,
  'annee' => :year,
  'annees' => :year,
  'year' => :year,
  'years' => :year,
  'mois' => :month,
  'month' => :month,
  'months' => :month,
  'week' => :week,
  'semaine' => :week,
  'weeks' => :week,
  'semaines' => :week,
  'jour' => :day,
  'day' => :day,
  'jours' => :day,
  'days' => :day,
  'heure' => :hour,
  'hour' => :hour,
  'heures' => :hour,
  'hours' => :hour,
  'minute' => :minute,
  'minutes' => :minute,
  'seconde' => :second,
  'second' => :second,
  'secondes' => :second,
  'seconds' => :second
}.freeze
KEYS =
TRANSLATIONS.keys.join('|').freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(expression = nil) ⇒ Delay


44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/delay.rb', line 44

def initialize(expression = nil)
  base = (expression.nil? ? nil : expression.dup)
  expression ||= []
  expression = expression.to_s.strip.split(/\s*\,\s*/) if expression.is_a?(String)
  unless expression.is_a?(Array)
    raise ArgumentError, "String or Array expected (got #{expression.class.name}:#{expression.inspect})"
  end
  @expression = expression.collect do |step|
    # step = step.mb_chars.downcase
    if step =~ /\A(eom|end of month|fdm|fin de mois)\z/
      [:eom]
    elsif step =~ /\A(bom|beginning of month|ddm|debut de mois|début de mois)\z/
      [:bom]
    elsif step =~ /\A\d+\ (#{KEYS})(\ (avant|ago))?\z/
      words = step.split(/\s+/).map(&:to_s)
      if TRANSLATIONS[words[1]].nil?
        raise InvalidDelayExpression, "#{words[1].inspect} is an undefined period (#{step.inspect} of #{base.inspect})"
      end
      [TRANSLATIONS[words[1]], (words[2].blank? ? 1 : -1) * words[0].to_i]
    elsif !step.blank?
      raise InvalidDelayExpression, "#{step.inspect} is an invalid step. (From #{base.inspect} => #{expression.inspect})"
    end
  end
end

Instance Attribute Details

#expressionObject (readonly)

Returns the value of attribute expression


42
43
44
# File 'lib/delay.rb', line 42

def expression
  @expression
end

Instance Method Details

#+(delay) ⇒ Object

Sums delays


118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/delay.rb', line 118

def +(delay)
  if delay.is_a?(Delay)
    Delay.new(to_s + ', ' + delay.to_s)
  elsif delay.is_a?(String)
    Delay.new(to_s + ', ' + Delay.new(delay).to_s)
  elsif delay.is_a?(Numeric)
    Delay.new(to_s + ', ' + delay.to_s + ' seconds')
  elsif delay.is_a?(Measure) && delay.dimension == :time && [:second, :minute, :hour, :day, :month, :year].include?(delay.unit)
    Delay.new(to_s + ', ' + delay.value.to_s + ' ' + delay.unit.to_s)
  else
    raise ArgumentError, "Cannot sum #{delay.class.name} to a #{self.class.name}"
  end
end

#-(delay) ⇒ Object

Adds opposites values of given delay


133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/delay.rb', line 133

def -(delay)
  if delay.is_a?(Delay)
    Delay.new(to_s + ', ' + delay.opposite.to_s)
  elsif delay.is_a?(String)
    Delay.new(to_s + ', ' + Delay.new(delay).opposite.to_s)
  elsif delay.is_a?(Numeric)
    Delay.new(to_s + ', ' + delay.to_s + ' seconds')
  elsif delay.is_a?(Measure) && delay.dimension == :time && [:second, :minute, :hour, :day, :month, :year].include?(delay.unit)
    Delay.new(to_s + ', ' + delay.value.to_s + ' ' + delay.unit.to_s + ' ago')
  else
    raise ArgumentError, "Cannot sum #{delay.class.name} to a #{self.class.name}"
  end
end

#compute(started_at = Time.zone.now) ⇒ Object


69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/delay.rb', line 69

def compute(started_at = Time.zone.now)
  return nil if started_at.nil?
  stopped_at = started_at.dup
  @expression.each do |step|
    case step[0]
    when :eom
      stopped_at = stopped_at.end_of_month
    when :bom
      stopped_at = stopped_at.beginning_of_month
    else
      stopped_at += step[1].send(step[0])
    end
  end
  stopped_at
end

#inspectObject


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

def inspect
  @expression.collect do |step|
    (step.size == 1 ? step[0].to_s.upcase : step[1].to_s + ' ' + step[0].to_s + 's')
  end.join(', ')
end

#invertObject

Return a duplicated inverted copy


113
114
115
# File 'lib/delay.rb', line 113

def invert
  dup.invert!
end

#invert!Object

Invert steps :

* EOM -> BOM
* BOM -> EOM
* x <duration> -> x <duration> ago

99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/delay.rb', line 99

def invert!
  @expression = @expression.collect do |step|
    if step == :eom
      :bom
    elsif step == :bom
      :eom
    else
      [step.first, -step.second]
    end
  end
  self
end

#to_sObject


91
92
93
# File 'lib/delay.rb', line 91

def to_s
  inspect
end