Module: Daru::DateTimeIndexHelper
- Defined in:
- lib/daru/date_time/index.rb
Overview
Private module for storing helper functions for DateTimeIndex.
Constant Summary collapse
- OFFSETS_HASH =
{ 'S' => Daru::Offsets::Second, 'M' => Daru::Offsets::Minute, 'H' => Daru::Offsets::Hour, 'D' => Daru::Offsets::Day, 'W' => Daru::Offsets::Week, 'MONTH' => Daru::Offsets::Month, 'MB' => Daru::Offsets::MonthBegin, 'ME' => Daru::Offsets::MonthEnd, 'YEAR' => Daru::Offsets::Year, 'YB' => Daru::Offsets::YearBegin, 'YE' => Daru::Offsets::YearEnd }.freeze
- TIME_INTERVALS =
{ Rational(1,1) => Daru::Offsets::Day, Rational(1,24) => Daru::Offsets::Hour, Rational(1,1440) => Daru::Offsets::Minute, Rational(1,86_400) => Daru::Offsets::Second }.freeze
- DOW_REGEXP =
Regexp.new(Daru::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
- DATE_PRECISION_REGEXP =
/^(\d\d\d\d)(-\d{1,2}(-\d{1,2}( \d{1,2}(:\d{1,2}(:\d{1,2})?)?)?)?)?$/
- 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/AbcSize,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 Daru::DateOffset object for generic offsets or one of the specialized classed within Daru::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
62 63 64 65 |
# File 'lib/daru/date_time/index.rb', line 62 def begin_from_offset? offset, start offset.is_a?(Daru::Offsets::Tick) || offset.respond_to?(:on_offset?) && offset.on_offset?(start) end |
.coerce_date(date) ⇒ Object
57 58 59 60 |
# File 'lib/daru/date_time/index.rb', line 57 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
117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/daru/date_time/index.rb', line 117 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
134 135 136 137 138 |
# File 'lib/daru/date_time/index.rb', line 134 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
111 112 113 114 115 |
# File 'lib/daru/date_time/index.rb', line 111 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
104 105 106 107 108 109 |
# File 'lib/daru/date_time/index.rb', line 104 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/AbcSize,Metrics/MethodLength
140 141 142 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 |
# File 'lib/daru/date_time/index.rb', line 140 def generate_bounds date_time, date_precision # rubocop:disable Metrics/AbcSize,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
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/daru/date_time/index.rb', line 67 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
93 94 95 96 97 98 99 100 101 102 |
# File 'lib/daru/date_time/index.rb', line 93 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 / Daru::Offsets::Second.new.multiplier Daru::Offsets::Second.new(number_of_seconds.numerator) if number_of_seconds.denominator == 1 end |
.key_out_of_bounds?(key, data) ⇒ Boolean
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/daru/date_time/index.rb', line 184 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
180 181 182 |
# File 'lib/daru/date_time/index.rb', line 180 def last_date data data.sort_by { |d| d[1] }.last end |
.offset_from_frequency(frequency) ⇒ Object
Generates a Daru::DateOffset object for generic offsets or one of the specialized classed within Daru::Offsets depending on the ‘frequency’ string.
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/daru/date_time/index.rb', line 38 def offset_from_frequency frequency return frequency if frequency.is_a?(Daru::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: Daru::DAYS_OF_WEEK[matched[:weekday]]) else offset_klass.new(n) end end |
.possibly_convert_to_date_time(data) ⇒ Object
176 177 178 |
# File 'lib/daru/date_time/index.rb', line 176 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
87 88 89 90 91 |
# File 'lib/daru/date_time/index.rb', line 87 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 |