Module: TimeCalc::Types

Extended by:
Types
Included in:
Types
Defined in:
lib/time_calc/types.rb

Overview

Tries to encapsulate all the differences between Time, Date, DateTime

Constant Summary collapse

ATTRS =
{
  'Time' => %i[year month day hour min sec subsec utc_offset],
  'Date' => %i[year month day],
  'DateTime' => %i[year month day hour min sec sec_fraction zone],
  'ActiveSupport::TimeWithZone' => %i[year month day hour min sec sec_fraction time_zone]
}.freeze
CLASS_NAME =

Because AS::TimeWithZone so frigging smart that it returns “Time” from redefined class name.

Class.instance_method(:name)

Instance Method Summary collapse

Instance Method Details

#compare(v1, v2) ⇒ Object



24
25
26
# File 'lib/time_calc/types.rb', line 24

def compare(v1, v2)
  compatible?(v1, v2) ? v1 <=> v2 : v1.to_time <=> v2.to_time
end

#compatible?(v1, v2) ⇒ Boolean

Returns:

  • (Boolean)


20
21
22
# File 'lib/time_calc/types.rb', line 20

def compatible?(v1, v2)
  [v1, v2].all?(Date) || [v1, v2].all?(Time)
end

#convert(v, klass) ⇒ Object



28
29
30
31
32
# File 'lib/time_calc/types.rb', line 28

def convert(v, klass)
  return v if v.class == klass

  v.public_send("to_#{klass.name.downcase}")
end

#merge_activesupport__timewithzone(value, **attrs) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/time_calc/types.rb', line 54

def merge_activesupport__timewithzone(value, **attrs)
  # You'd imagine we should be able to use just value.change(...) ActiveSupport's API here...
  # But it is not available if you don't require all the core_ext's of Time, so I decided to
  # be on the safe side and use similar approach everywhere.

  # When we truncate, we use :subsec key as a sign to zeroefy second fractions
  attrs[:sec_fraction] ||= attrs.delete(:subsec) if attrs.key?(:subsec)

  _merge(value, **attrs)
    .then { |components|
      zone = components.delete(:time_zone)
      components.merge!(mday: components.delete(:day), mon: components.delete(:month))
      zone.__send__(:parts_to_time, components, value)
    }
end

#merge_date(value, **attrs) ⇒ Object



41
42
43
# File 'lib/time_calc/types.rb', line 41

def merge_date(value, **attrs)
  _merge(value, **attrs).values.then { |components| Date.new(*components) }
end

#merge_datetime(value, **attrs) ⇒ Object



45
46
47
48
49
50
51
52
# File 'lib/time_calc/types.rb', line 45

def merge_datetime(value, **attrs)
  # When we truncate, we use :subsec key as a sign to zeroefy second fractions
  attrs[:sec_fraction] ||= attrs.delete(:subsec) if attrs.key?(:subsec)

  _merge(value, **attrs)
    .tap { |h| h[:sec] += h.delete(:sec_fraction) }
    .values.then { |components| DateTime.new(*components) }
end

#merge_time(value, **attrs) ⇒ Object



34
35
36
37
38
39
# File 'lib/time_calc/types.rb', line 34

def merge_time(value, **attrs)
  _merge(value, **attrs)
    .tap { |h| h[:sec] += h.delete(:subsec) }
    .then { |h| fix_time_zone(h, value) }
    .values.then { |components| Time.new(*components) }
end