Skip to content

Commit 1b9c2a1

Browse files
committed
+Op
1 parent 33e004d commit 1b9c2a1

File tree

3 files changed

+46
-27
lines changed

3 files changed

+46
-27
lines changed

lib/time_calc.rb

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# frozen_string_literal: true
22

3-
require_relative 'time_calc/units'
4-
require_relative 'time_calc/util'
3+
require_relative 'time_calc/value'
54

65
class TimeCalc
76
class << self
@@ -10,41 +9,38 @@ class << self
109
def now
1110
new(Time.now)
1211
end
13-
end
1412

15-
OPERATIONS = %i[+ - floor ceil round].freeze
13+
def from(time)
14+
Value.new(time)
15+
end
1616

17-
attr_reader :source, :operations
17+
def from_now
18+
from(Time.now)
19+
end
20+
end
1821

19-
def initialize(source)
20-
@source = source
22+
def initialize(time)
23+
@value = Value.new(time)
2124
end
2225

2326
def inspect
24-
'<%s(%p)>' % [self.class, source]
27+
'<%s(%p)>' % [self.class, @value.to_time]
2528
end
2629

27-
def op(name, span, unit)
28-
OPERATIONS.include?(name) or fail ArgumentError, "Unrecognized operation #{name.inspect}"
29-
Units.get(unit).public_send(name, source, span)
30-
end
30+
OPERATIONS = %i[merge truncate floor ceil round + -].freeze
3131

3232
OPERATIONS.each do |name|
33-
define_method(name) { |span, unit = nil|
34-
# allow +(:year) and +(3, :years) call-sequences
35-
# ...and round(:tuesday) instead of round(1/7r, :week)
36-
span, unit = guess_span(span) if unit.nil?
37-
op(name, span, unit)
38-
}
33+
define_method(name) { |*args| @value.public_send(name, *args).to_time }
3934
end
4035

41-
private
42-
43-
def guess_span(unit)
44-
if (wday = WEEKDAYS.index(unit))
45-
[Rational(wday, 7), :weeks]
46-
else
47-
[1, unit]
36+
class << self
37+
OPERATIONS.each do |name|
38+
define_method(name) { |*args| Op.new([[name, *args]]) }
4839
end
4940
end
41+
42+
# the rest: just delegate
43+
5044
end
45+
46+
require_relative 'time_calc/op'

lib/time_calc/op.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
class TimeCalc
2+
class Op
3+
def initialize(chain = [])
4+
@chain = chain
5+
end
6+
7+
def inspect
8+
'<%s %s>' % [self.class, @chain.map { |name, *args| "#{name}(#{args.join(' ')})"}.join('.')]
9+
end
10+
11+
TimeCalc::OPERATIONS.each do |name|
12+
define_method(name) { |*args| Op.new([*@chain, [name, *args]]) }
13+
end
14+
15+
def call(time)
16+
@chain.reduce(Value.new(time)) { |val, (name, *args)| val.public_send(name, *args) }.to_time
17+
end
18+
19+
def to_proc
20+
method(:call).to_proc
21+
end
22+
end
23+
end

lib/time_calc/value.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ class Value
1818
}.freeze
1919
UNITS = %i[year month day hour min sec subsec].freeze
2020
ALL_UNITS = %i[year month week day hour min sec].freeze
21-
CONSTRUCT_UNITS = %i[year month day hour min sec].freeze
2221
MULTIPLIERS = {
2322
sec: 1,
2423
min: 60,
@@ -40,9 +39,10 @@ class Value
4039

4140
def self.from_h(hash, utc_offset: Time.now.utc_offset)
4241
hash
42+
.slice(*UNITS)
4343
.merge(EMPTY_HASH) { |_k, val, empty| val || empty }
4444
.tap { |h| h[:sec] += h.delete(:subsec) }
45-
.values_at(*CONSTRUCT_UNITS)
45+
.values
4646
.then { |components| Value.new(Time.new(*components, utc_offset)) }
4747
end
4848

0 commit comments

Comments
 (0)