Module: DaruLite::DateTimeIndexHelper
- Defined in:
- lib/daru_lite/date_time/index.rb
Overview
Private module for storing helper functions for DateTimeIndex.
Constant Summary collapse
- OFFSETS_HASH =
{ 'S' => DaruLite::Offsets::Second, 'M' => DaruLite::Offsets::Minute, 'H' => DaruLite::Offsets::Hour, 'D' => DaruLite::Offsets::Day, 'W' => DaruLite::Offsets::Week, 'MONTH' => DaruLite::Offsets::Month, 'MB' => DaruLite::Offsets::MonthBegin, 'ME' => DaruLite::Offsets::MonthEnd, 'YEAR' => DaruLite::Offsets::Year, 'YB' => DaruLite::Offsets::YearBegin, 'YE' => DaruLite::Offsets::YearEnd }.freeze
- TIME_INTERVALS =
{ Rational(1, 1) => DaruLite::Offsets::Day, Rational(1, 24) => DaruLite::Offsets::Hour, Rational(1, 1440) => DaruLite::Offsets::Minute, Rational(1, 86_400) => DaruLite::Offsets::Second }.freeze
- DOW_REGEXP =
Regexp.new(DaruLite::DAYS_OF_WEEK.keys.join('|'))
- FREQUENCY_PATTERN =
/^ (?<multiplier>[0-9]+)? ( (?<offset>MONTH|YEAR|S|H|MB|ME|M|D|YB|YE) | (?<offset>W)(-(?<weekday>#{DOW_REGEXP}))? )$/x.freeze
- DATE_PRECISION_REGEXP =
/^(\d\d\d\d)(-\d{1,2}(-\d{1,2}( \d{1,2}(:\d{1,2}(:\d{1,2})?)?)?)?)?$/.freeze
- DATE_PRECISIONS =
[nil, :year, :month, :day, :hour, :min, :sec].freeze
Class Method Summary collapse
- .begin_from_offset?(offset, start) ⇒ Boolean
- .coerce_date(date) ⇒ Object
- .date_time_from(date_string, date_precision) ⇒ Object
- .determine_date_precision_of(date_string) ⇒ Object
- .find_date_string_bounds(date_string) ⇒ Object
- .find_index_of_date(data, date_time) ⇒ Object
-
.generate_bounds(date_time, date_precision) ⇒ Object
rubocop:disable Metrics/MethodLength.
- .generate_data(start, en, offset, periods) ⇒ Object
- .infer_offset(data) ⇒ Object
- .key_out_of_bounds?(key, data) ⇒ Boolean
- .last_date(data) ⇒ Object
-
.offset_from_frequency(frequency) ⇒ Object
Generates a DaruLite::DateOffset object for generic offsets or one of the specialized classed within DaruLite::Offsets depending on the ‘frequency’ string.
- .possibly_convert_to_date_time(data) ⇒ Object
- .verify_start_and_end(start, en) ⇒ Object
Class Method Details
.begin_from_offset?(offset, start) ⇒ Boolean
64 65 66 67 |
# File 'lib/daru_lite/date_time/index.rb', line 64 def begin_from_offset?(offset, start) offset.is_a?(DaruLite::Offsets::Tick) || (offset.respond_to?(:on_offset?) && offset.on_offset?(start)) end |
.coerce_date(date) ⇒ Object
58 59 60 61 62 |
# File 'lib/daru_lite/date_time/index.rb', line 58 def coerce_date(date) return date unless date.is_a?(String) date_time_from(date, determine_date_precision_of(date)) end |
.date_time_from(date_string, date_precision) ⇒ Object
120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/daru_lite/date_time/index.rb', line 120 def date_time_from(date_string, date_precision) case date_precision when :year DateTime.new(date_string.gsub(/[^0-9]/, '').to_i) when :month DateTime.new( date_string.match(/\d\d\d\d/).to_s.to_i, date_string.match(/-\d?\d/).to_s.delete('-').to_i ) else DateTime.parse date_string end end |
.determine_date_precision_of(date_string) ⇒ Object
137 138 139 140 141 |
# File 'lib/daru_lite/date_time/index.rb', line 137 def determine_date_precision_of(date_string) components = date_string.scan(DATE_PRECISION_REGEXP).flatten.compact DATE_PRECISIONS[components.count] or raise ArgumentError, "Unacceptable date string #{date_string}" end |
.find_date_string_bounds(date_string) ⇒ Object
114 115 116 117 118 |
# File 'lib/daru_lite/date_time/index.rb', line 114 def find_date_string_bounds(date_string) date_precision = determine_date_precision_of date_string date_time = date_time_from date_string, date_precision generate_bounds date_time, date_precision end |
.find_index_of_date(data, date_time) ⇒ Object
107 108 109 110 111 112 |
# File 'lib/daru_lite/date_time/index.rb', line 107 def find_index_of_date(data, date_time) searched = data.bsearch { |d| d[0] >= date_time } raise(ArgumentError, "Cannot find #{date_time}") if searched.nil? || searched[0] != date_time searched[1] end |
.generate_bounds(date_time, date_precision) ⇒ Object
rubocop:disable Metrics/MethodLength
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/daru_lite/date_time/index.rb', line 143 def generate_bounds(date_time, date_precision) # rubocop:disable Metrics/MethodLength # FIXME: about that ^ disable: I'd like to use my zverok/time_boots here, which will simplify things case date_precision when :year [ date_time, DateTime.new(date_time.year, 12, 31, 23, 59, 59) ] when :month [ date_time, DateTime.new(date_time.year, date_time.month, ((date_time >> 1) - 1).day, 23, 59, 59) ] when :day [ date_time, DateTime.new(date_time.year, date_time.month, date_time.day, 23, 59, 59) ] when :hour [ date_time, DateTime.new(date_time.year, date_time.month, date_time.day, date_time.hour, 59, 59) ] when :min [ date_time, DateTime.new(date_time.year, date_time.month, date_time.day, date_time.hour, date_time.min, 59) ] else # second or when precision is same as offset [date_time, date_time] end end |
.generate_data(start, en, offset, periods) ⇒ Object
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/daru_lite/date_time/index.rb', line 69 def generate_data(start, en, offset, periods) data = [] new_date = begin_from_offset?(offset, start) ? start : offset + start if periods.nil? # use end loop do break if new_date > en data << new_date new_date = offset + new_date end else periods.times do data << new_date new_date = offset + new_date end end data end |
.infer_offset(data) ⇒ Object
96 97 98 99 100 101 102 103 104 105 |
# File 'lib/daru_lite/date_time/index.rb', line 96 def infer_offset(data) diffs = data.each_cons(2).map { |d1, d2| d2 - d1 } return nil unless diffs.uniq.count == 1 return TIME_INTERVALS[diffs.first].new if TIME_INTERVALS.include?(diffs.first) number_of_seconds = diffs.first / DaruLite::Offsets::Second.new.multiplier DaruLite::Offsets::Second.new(number_of_seconds.numerator) if number_of_seconds.denominator == 1 end |
.key_out_of_bounds?(key, data) ⇒ Boolean
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/daru_lite/date_time/index.rb', line 187 def key_out_of_bounds?(key, data) dates = data.transpose.first precision = determine_date_precision_of key date_time = date_time_from key, precision # FIXME: I'm pretty suspicious about logic here: # why only year & month? - zverok 2016-05-16 case precision when :year year_out_of_bounds?(date_time, dates) when :month year_month_out_of_bounds?(date_time, dates) end end |
.last_date(data) ⇒ Object
183 184 185 |
# File 'lib/daru_lite/date_time/index.rb', line 183 def last_date(data) data.max_by { |d| d[1] } end |
.offset_from_frequency(frequency) ⇒ Object
Generates a DaruLite::DateOffset object for generic offsets or one of the specialized classed within DaruLite::Offsets depending on the ‘frequency’ string.
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/daru_lite/date_time/index.rb', line 38 def offset_from_frequency(frequency) return frequency if frequency.is_a?(DaruLite::DateOffset) frequency ||= 'D' matched = FREQUENCY_PATTERN.match(frequency) or raise ArgumentError, "Invalid frequency string #{frequency}" n = (matched[:multiplier] || 1).to_i offset_string = matched[:offset] offset_klass = OFFSETS_HASH[offset_string] or raise ArgumentError, "Cannont interpret offset #{offset_string}" if offset_string == 'W' offset_klass.new(n, weekday: DaruLite::DAYS_OF_WEEK[matched[:weekday]]) else offset_klass.new(n) end end |
.possibly_convert_to_date_time(data) ⇒ Object
179 180 181 |
# File 'lib/daru_lite/date_time/index.rb', line 179 def possibly_convert_to_date_time(data) data[0].is_a?(String) ? data.map! { |e| DateTime.parse(e) } : data end |
.verify_start_and_end(start, en) ⇒ Object
90 91 92 93 94 |
# File 'lib/daru_lite/date_time/index.rb', line 90 def verify_start_and_end(start, en) raise ArgumentError, 'Start and end cannot be the same' if start == en raise ArgumentError, 'Start must be lesser than end' if start > en raise ArgumentError, 'Only same time zones are allowed' if start.zone != en.zone end |