Class: TimeCalc::Diff

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/time_calc/diff.rb

Overview

Represents difference between two time-or-date values.

Typically created with just

“‘ruby TimeCalc.(t1) - t2 “`

Allows to easily and correctly calculate number of years/monthes/days/etc between two points in time.

Examples:

t1 = Time.parse('2019-06-01 14:50')
t2 = Time.parse('2019-06-15 12:10')
(TimeCalc.(t2) - t1).div(:day)
# => 13
# the same:
(TimeCalc.(t2) - t1).days
# => 13
(TimeCalc.(t2) - t1).div(3, :hours)
# => 111

(TimeCalc.(t2) - t1).factorize
# => {:year=>0, :month=>0, :week=>1, :day=>6, :hour=>21, :min=>20, :sec=>0}
(TimeCalc.(t2) - t1).factorize(weeks: false)
# => {:year=>0, :month=>0, :day=>13, :hour=>21, :min=>20, :sec=>0}
(TimeCalc.(t2) - t1).factorize(weeks: false, zeroes: false)
# => {:day=>13, :hour=>21, :min=>20, :sec=>0}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(from, to) ⇒ Diff

Note:

Typically you should prefer TimeCalc#- to create Diff.

Returns a new instance of Diff.



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

def initialize(from, to)
  @from, @to = coerce(try_unwrap(from), try_unwrap(to)).map(&Value.method(:wrap))
end

Instance Attribute Details

#fromObject (readonly)



35
36
37
# File 'lib/time_calc/diff.rb', line 35

def from
  @from
end

#toObject (readonly)



35
36
37
# File 'lib/time_calc/diff.rb', line 35

def to
  @to
end

Instance Method Details

#-@Diff

“Negates” the diff by swapping its operands.



53
54
55
# File 'lib/time_calc/diff.rb', line 53

def -@
  Diff.new(to, from)
end

#<=>(other) ⇒ -1, ...



192
193
194
195
196
# File 'lib/time_calc/diff.rb', line 192

def <=>(other)
  return unless other.is_a?(Diff)

  exact <=> other.exact
end

#daysInteger

Whole days in diff.



# File 'lib/time_calc/diff.rb', line 98


#div(span, unit) ⇒ Integer #div(unit) ⇒ Integer Also known as: /

Returns Number of whole ‘<unit>`s between `Diff`’s operands.

Examples:

t1 = Time.parse('2019-06-01 14:50')
t2 = Time.parse('2019-06-15 12:10')
(TimeCalc.(t2) - t1).div(:day)
# => 13
(TimeCalc.(t2) - t1).div(3, :hours)
# => 111

Overloads:

  • #div(unit) ⇒ Integer

    Shortcut for ‘div(1, unit)`. Also can called as just `.<units>` methods (like #years)



90
91
92
93
94
95
96
# File 'lib/time_calc/diff.rb', line 90

def div(span, unit = nil)
  return -(-self).div(span, unit) if negative?

  span, unit = 1, span if unit.nil?
  unit = Units.(unit)
  singular_div(unit).div(span)
end

#divmod(span, unit) ⇒ (Integer, Time or Date or DateTime) #divmod(unit) ⇒ (Integer, Time or Date or DateTime)

Combination of #div and #modulo in one operation.

Overloads:

  • #divmod(unit) ⇒ (Integer, Time or Date or DateTime)

    Shortcut for ‘divmod(1, unit)`



68
69
70
71
# File 'lib/time_calc/diff.rb', line 68

def divmod(span, unit = nil)
  span, unit = 1, span if unit.nil?
  div(span, unit).then { |res| [res, to.+(res * span, unit).unwrap] }
end

#exactObject



177
178
179
# File 'lib/time_calc/diff.rb', line 177

def exact
  from.unwrap.to_time - to.unwrap.to_time
end

#factorize(zeroes: true, max: :year, min: :sec, weeks: true) ⇒ Hash<Symbol => Integer>

“Factorizes” the distance between two points in time into units: years, months, weeks, days.

Examples:

t1 = Time.parse('2019-06-01 14:50')
t2 = Time.parse('2019-06-15 12:10')
(TimeCalc.(t2) - t1).factorize
# => {:year=>0, :month=>0, :week=>1, :day=>6, :hour=>21, :min=>20, :sec=>0}
(TimeCalc.(t2) - t1).factorize(weeks: false)
# => {:year=>0, :month=>0, :day=>13, :hour=>21, :min=>20, :sec=>0}
(TimeCalc.(t2) - t1).factorize(weeks: false, zeroes: false)
# => {:day=>13, :hour=>21, :min=>20, :sec=>0}
(TimeCalc.(t2) - t1).factorize(max: :hour)
# => {:hour=>333, :min=>20, :sec=>0}
(TimeCalc.(t2) - t1).factorize(max: :hour, min: :min)
# => {:hour=>333, :min=>20}


160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/time_calc/diff.rb', line 160

def factorize(zeroes: true, max: :year, min: :sec, weeks: true)
  t = to
  f = from
  select_units(max: Units.(max), min: Units.(min), weeks: weeks)
    .inject({}) { |res, unit|
      span, t = Diff.new(f, t).divmod(unit)
      res.merge(unit => span)
    }.then { |res|
      next res if zeroes

      res.drop_while { |_, v| v.zero? }.to_h
    }
end

#hoursInteger

Whole hours in diff.



# File 'lib/time_calc/diff.rb', line 98


#inspectObject



47
48
49
# File 'lib/time_calc/diff.rb', line 47

def inspect
  '#<%s(%s − %s)>' % [self.class, from.unwrap, to.unwrap]
end

#minutesInteger

Whole minutes in diff.



# File 'lib/time_calc/diff.rb', line 98


#modulo(span, unit) ⇒ Time, Date or DateTime #modulo(unit) ⇒ Time, Date or DateTime Also known as: %

Same as integer modulo: the “rest” of whole division of the distance between two time points by ‘<span> <units>`. This rest will be also time point, equal to `first diff operand - span units`

Overloads:

  • #modulo(unit) ⇒ Time, Date or DateTime

    Shortcut for ‘modulo(1, unit)`.



132
133
134
# File 'lib/time_calc/diff.rb', line 132

def modulo(span, unit = nil)
  divmod(span, unit).last
end

#monthsInteger

Whole months in diff.



# File 'lib/time_calc/diff.rb', line 98


#negative?true, false



182
183
184
# File 'lib/time_calc/diff.rb', line 182

def negative?
  exact.negative?
end

#positive?true, false



187
188
189
# File 'lib/time_calc/diff.rb', line 187

def positive?
  exact.positive?
end

#secondsInteger

Whole seconds in diff.



# File 'lib/time_calc/diff.rb', line 98


#weeksInteger

Whole weeks in diff.



# File 'lib/time_calc/diff.rb', line 98


#yearsInteger

Whole years in diff.



# File 'lib/time_calc/diff.rb', line 98