Class: TimeCalc

Inherits:
Object
  • Object
show all
Defined in:
lib/time_calc.rb,
lib/time_calc/op.rb,
lib/time_calc/dst.rb,
lib/time_calc/diff.rb,
lib/time_calc/types.rb,
lib/time_calc/units.rb,
lib/time_calc/value.rb,
lib/time_calc/version.rb,
lib/time_calc/sequence.rb

Overview

Module for time arithmetic.

Examples of usage:

“‘ruby TimeCalc.(Time.now).+(1, :day) # => 2019-07-04 23:28:54 0300 TimeCalc.(Time.now).round(:hour) # => 2019-07-03 23:00:00 0300

# Operations with Time.now and Date.today also have their shortcuts: TimeCalc.now.-(3, :days) # => 2019-06-30 23:28:54 0300 TimeCalc.today.ceil(:month) # => #<Date: 2019-08-01 ((2458697j,0s,0n),0s,2299161j)>

# If you need to perform several operations TimeCalc.from wraps your value: TimeCalc.from(Time.parse(‘2019-06-14 13:40’)).+(10, :days).floor(:week).unwrap # => 2019-06-24 00:00:00 +0300

# TimeCalc#- also can be used to calculate difference between time values diff = TimeCalc.(Time.parse(‘2019-07-03 23:32’)) - Time.parse(‘2019-06-14 13:40’) # => #<TimeCalc::Diff(2019-07-03 23:32:00 0300 − 2019-06-14 13:40:00 0300)> diff.days # => 19 diff.hours # => 465 diff.factorize # => :month=>0, :week=>2, :day=>5, :hour=>9, :min=>52, :sec=>0 diff.factorize(max: :day) # => :hour=>9, :min=>52, :sec=>0

# Enumerable sequences of time values sequence = TimeCalc.(Time.parse(‘2019-06-14 13:40’))

.to(Time.parse('2019-07-03 23:32'))
.step(5, :hours)

# => #<TimeCalc::Sequence (2019-06-14 13:40:00 0300 - 2019-07-03 23:32:00 0300):step(5 hours)> sequence.to_a # => [2019-06-14 13:40:00 0300, 2019-06-14 18:40:00 0300, 2019-06-14 23:40:00 0300, … sequence.first(2) # => [2019-06-14 13:40:00 0300, 2019-06-14 18:40:00 +0300]

# Construct operations to apply as a proc: times = [‘2019-06-01 14:30’, ‘2019-06-05 17:10’, ‘2019-07-02 13:40’].map { |t| Time.parse(t) } # => [2019-06-01 14:30:00 0300, 2019-06-05 17:10:00 0300, 2019-07-02 13:40:00 0300] times.map(&TimeCalc.(1, :week).round(:day)) # => [2019-06-09 00:00:00 0300, 2019-06-13 00:00:00 0300, 2019-07-10 00:00:00 +0300] “‘

See method docs below for details and supported arguments.

Defined Under Namespace

Modules: DST, Types, Units Classes: Diff, Op, Sequence, Value

Constant Summary collapse

MATH_OPERATIONS =
%i[merge truncate floor ceil round + - iterate].freeze
OPERATIONS =
MATH_OPERATIONS.+(%i[to step for]).freeze
VERSION =
'0.0.4'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(date_or_time) ⇒ TimeCalc

Creates a “temporary” wrapper, which would be unwrapped after first operation:

“‘ruby TimeCalc.new(Time.now).round(:hour) # => 2019-07-03 23:00:00 +0300 “`

The constructor also aliased as ‘.call` which allows for nicer (for some eyes) code:

“‘ruby TimeCalc.(Time.now).round(:hour) # => 2019-07-03 23:00:00 +0300

# There is another shortcut for those who disapprove on ‘.()` TimeCalc.+(1, :month) “`

See from if you need to perform several math operations on same value.

Parameters:

  • date_or_time (Time, Date, DateTime)


130
131
132
# File 'lib/time_calc.rb', line 130

def initialize(date_or_time)
  @value = Value.new(date_or_time)
end

Instance Attribute Details

#valueObject (readonly)



108
109
110
# File 'lib/time_calc.rb', line 108

def value
  @value
end

Class Method Details

.+(span, unit) ⇒ Op

Creates operation to perform #+‘(span, unit)`

Returns:



3
# File 'lib/time_calc.rb', line 3

def TimeCalc.+(span, unit); end

.-(span, unit) ⇒ Op

Returns:



9
# File 'lib/time_calc.rb', line 9

def TimeCalc.-(span, unit); end

.ceil(unit) ⇒ Op

Returns:



15
# File 'lib/time_calc.rb', line 15

def TimeCalc.ceil(unit); end

.floor(unit) ⇒ Op

Returns:



12
# File 'lib/time_calc.rb', line 12

def TimeCalc.floor(unit); end

.from(date_or_time) ⇒ Value Also known as: wrap

Returns Value wrapper, useful for performing several operations at once:

“‘ruby TimeCalc.from(Time.parse(’2019-06-14 13:40’)).+(10, :days).floor(:week).unwrap # => 2019-06-24 00:00:00 +0300 “‘

Parameters:

  • date_or_time (Time, Date, DateTime)

Returns:



86
87
88
# File 'lib/time_calc.rb', line 86

def from(date_or_time)
  Value.new(date_or_time)
end

.from_nowValue Also known as: wrap_now

Shortcut for ‘TimeCalc.from(Time.now)`

Returns:



92
93
94
# File 'lib/time_calc.rb', line 92

def from_now
  from(Time.now)
end

.from_todayValue Also known as: wrap_today

Shortcut for ‘TimeCalc.from(Date.today)`

Returns:



98
99
100
# File 'lib/time_calc.rb', line 98

def from_today
  from(Date.today)
end

.iterate(span, unit, &block) ⇒ Op

Returns:



6
# File 'lib/time_calc.rb', line 6

def TimeCalc.iterate(span, unit, &block); end

.nowTimeCalc

Shortcut for ‘TimeCalc.(Time.now)`

Returns:



67
68
69
# File 'lib/time_calc.rb', line 67

def now
  new(Time.now)
end

.round(unit) ⇒ Op

Returns:



18
# File 'lib/time_calc.rb', line 18

def TimeCalc.round(unit); end

.todayTimeCalc

Shortcut for ‘TimeCalc.(Date.today)`

Returns:



73
74
75
# File 'lib/time_calc.rb', line 73

def today
  new(Date.today)
end

Instance Method Details

#+(span, unit) ⇒ Date, ...

Add ‘<span units>` to wrapped value

Examples:

TimeCalc.(Time.parse('2019-07-03 23:28:54')).+(1, :day)
# => 2019-07-04 23:28:54 +0300

Parameters:

  • span (Integer)
  • unit (Symbol)

Returns:

  • (Date, Time, DateTime)

    value of the same type that was initial wrapped value.



# File 'lib/time_calc.rb', line 184

#-(span, unit) ⇒ Date, ... #-(date_or_time) ⇒ Diff

Overloads:

  • #-(span, unit) ⇒ Date, ...

    Subtracts ‘span units` from wrapped value.

    Parameters:

    • span (Integer)
    • unit (Symbol)

    Returns:

    • (Date, Time, DateTime)

      value of the same type that was initial wrapped value.

  • #-(date_or_time) ⇒ Diff

    Produces Diff, allowing to calculate structured difference 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).days
    # => 13

    Parameters:

    • date_or_time (Date, Time, DateTime)

    Returns:

Returns:



# File 'lib/time_calc.rb', line 224

#==(other) ⇒ true, false

Returns:

  • (true, false)


140
141
142
# File 'lib/time_calc.rb', line 140

def ==(other)
  other.is_a?(self.class) && other.value == value
end

#ceil(unit) ⇒ Time, ...

Ceils (rounds up) date/time to nearest ‘unit`.

Examples:

TimeCalc.(Time.parse('2018-06-23 12:30')).ceil(:month)
# => 2018-07-01 00:00:00 +0300

Parameters:

  • unit (Symbol)

Returns:

  • (Time, Date, DateTime)

    value of the same type that was initial wrapped value.



# File 'lib/time_calc.rb', line 164

#floor(unit) ⇒ Time, ...

Floors (rounds down) date/time to nearest ‘unit`.

Examples:

TimeCalc.(Time.parse('2018-06-23 12:30')).floor(:month)
# => 2018-06-01 00:00:00 +0300

Parameters:

  • unit (Symbol)

Returns:

  • (Time, Date, DateTime)

    value of the same type that was initial wrapped value.



# File 'lib/time_calc.rb', line 154

#for(span, unit) ⇒ Sequence

Produces Sequence from this value to ‘this + <span units>`

Examples:

TimeCalc.(Time.parse('2019-06-01 14:50')).for(2, :weeks).step(1, :day).count
# => 15

Parameters:

  • span (Integer)
  • unit (Symbol)

Returns:



# File 'lib/time_calc.rb', line 261

#inspectObject



135
136
137
# File 'lib/time_calc.rb', line 135

def inspect
  '#<%s(%s)>' % [self.class, @value.unwrap]
end

#iterate(span, unit) {|Time/Date/DateTime| ... } ⇒ Date, ...

Like #+, but allows conditional skipping of some periods. Increases value by ‘unit` at least `span` times, on each iteration checking with block provided if this point matches desired period; if it is not, it is skipped without increasing iterations counter. Useful for “business date/time” algorithms.

Examples:

# add 10 working days.
TimeCalc.(Time.parse('2019-07-03 23:28:54')).iterate(10, :days) { |t| (1..5).cover?(t.wday) }
# => 2019-07-17 23:28:54 +0300

# add 12 working hours
TimeCalc.(Time.parse('2019-07-03 13:28:54')).iterate(12, :hours) { |t| (9...18).cover?(t.hour) }
# => 2019-07-04 16:28:54 +0300

# negative spans are working, too:
TimeCalc.(Time.parse('2019-07-03 13:28:54')).iterate(-12, :hours) { |t| (9...18).cover?(t.hour) }
# => 2019-07-02 10:28:54 +0300

# zero span could be used to robustly enforce value into acceptable range
# (increasing forward till block is true):
TimeCalc.(Time.parse('2019-07-03 23:28:54')).iterate(0, :hours) { |t| (9...18).cover?(t.hour) }
# => 2019-07-04 09:28:54 +0300

Parameters:

  • span (Integer)

    Could be positive or negative

  • unit (Symbol)

Yields:

  • (Time/Date/DateTime)

    Object of wrapped class

Yield Returns:

  • (true, false)

    If this point in time is “suitable”. If the falsey value is returned, iteration is skipped without increasing the counter.

Returns:

  • (Date, Time, DateTime)

    value of the same type that was initial wrapped value.



# File 'lib/time_calc.rb', line 193

#merge(**attrs) ⇒ Time, ...

Replaces specified components of date/time, preserves the rest.

Examples:

TimeCalc.(Date.parse('2018-06-01')).merge(year: 1983)
# => #<Date: 1983-06-01>

Parameters:

  • attrs (Hash<Symbol => Integer>)

Returns:

  • (Time, Date, DateTime)

    value of the same type that was initial wrapped value.



# File 'lib/time_calc.rb', line 144

#round(unit) ⇒ Time, ...

Rounds (up or down) date/time to nearest ‘unit`.

Examples:

TimeCalc.(Time.parse('2018-06-23 12:30')).round(:month)
# => 2018-07-01 00:00:00 +0300

Parameters:

  • unit (Symbol)

Returns:

  • (Time, Date, DateTime)

    value of the same type that was initial wrapped value.



# File 'lib/time_calc.rb', line 174

#step(unit) ⇒ Sequence #step(span, unit) ⇒ Sequence

Produces endless Sequence from this value, with step specified.

Overloads:

  • #step(unit) ⇒ Sequence

    Shortcut for ‘step(1, unit)`

    Parameters:

    • unit (Symbol)
  • #step(span, unit) ⇒ Sequence

    Examples:

    TimeCalc.(Time.parse('2019-06-01 14:50')).step(1, :day).take(3)
    # => [2019-06-01 14:50:00 +0300, 2019-06-02 14:50:00 +0300, 2019-06-03 14:50:00 +0300]

    Parameters:

    • span (Integer)
    • unit (Symbol)

Returns:



# File 'lib/time_calc.rb', line 247

#to(date_or_time) ⇒ Sequence

Produces Sequence from this value to ‘date_or_time`

Parameters:

  • date_or_time (Date, Time, DateTime)

Returns:



# File 'lib/time_calc.rb', line 241