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.

Parameters:

  • from (Time, Date, DateTime)
  • to (Time, Date, DateTime)


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.

Returns:



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

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

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

Returns:

  • (-1, 0, 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.

Returns:

  • (Integer)


# 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(span, unit) ⇒ Integer

    Parameters:

    • span (Integer)
    • unit (Symbol)

      Any of supported units (see TimeCalc)

  • #div(unit) ⇒ Integer

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

    Parameters:

    • unit (Symbol)

      Any of supported units (see TimeCalc)

Returns:

  • (Integer)

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



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(span, unit) ⇒ (Integer, Time or Date or DateTime)

    Parameters:

    • span (Integer)
    • unit (Symbol)

      Any of supported units (see TimeCalc)

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

    Shortcut for ‘divmod(1, unit)`

    Parameters:

    • unit (Symbol)

      Any of supported units (see TimeCalc)

Returns:

  • ((Integer, Time or Date or DateTime))


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}

Parameters:

  • zeroes (true, false) (defaults to: true)

    Include big units (for ex., year), if they are zero

  • weeks (true, false) (defaults to: true)

    Include weeks

  • max (Symbol) (defaults to: :year)

    Max unit to factorize into, from all supported units list

  • min (Symbol) (defaults to: :sec)

    Min unit to factorize into, from all supported units list

Returns:

  • (Hash<Symbol => Integer>)


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.

Returns:

  • (Integer)


# 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.

Returns:

  • (Integer)


# 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(span, unit) ⇒ Time, Date or DateTime

    Parameters:

    • span (Integer)
    • unit (Symbol)

      Any of supported units (see TimeCalc)

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

    Shortcut for ‘modulo(1, unit)`.

    Parameters:

    • unit (Symbol)

      Any of supported units (see TimeCalc)

Returns:

  • (Time, Date or DateTime)

    Value is always the same type as first diff operand



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.

Returns:

  • (Integer)


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

#negative?true, false

Returns:

  • (true, false)


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

def negative?
  exact.negative?
end

#positive?true, false

Returns:

  • (true, false)


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

def positive?
  exact.positive?
end

#secondsInteger

Whole seconds in diff.

Returns:

  • (Integer)


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

#weeksInteger

Whole weeks in diff.

Returns:

  • (Integer)


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

#yearsInteger

Whole years in diff.

Returns:

  • (Integer)


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