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
}
TIME_INTERVALS =
{
  Rational(1,1)     => Daru::Offsets::Day,
  Rational(1,24)    => Daru::Offsets::Hour,
  Rational(1,1440)  => Daru::Offsets::Minute,
  Rational(1,86400) => Daru::Offsets::Second
}

Class Method Summary collapse

Class Method Details

.begin_from_offset?(offset, start) ⇒ Boolean

Returns:

  • (Boolean)


63
64
65
66
67
68
69
70
# File 'lib/daru/date_time/index.rb', line 63

def begin_from_offset? offset, start
  if offset.kind_of?(Daru::Offsets::Tick) or 
    (offset.respond_to?(:on_offset?) and offset.on_offset?(start))
    true
  else
    false
  end
end

.date_time_from(date_string, date_precision) ⇒ Object



128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/daru/date_time/index.rb', line 128

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.gsub("-",'').to_i)
  else
    DateTime.parse date_string
  end
end

.determine_date_precision_of(date_string) ⇒ Object



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/daru/date_time/index.rb', line 141

def determine_date_precision_of date_string
  case date_string
  when /\d\d\d\d\-\d?\d\-\d?\d \d?\d:\d?\d:\d?\d/
    :sec
  when /\d\d\d\d\-\d?\d\-\d?\d \d?\d:\d?\d/
    :min
  when /\d\d\d\d\-\d?\d\-\d?\d \d?\d/
    :hour
  when /\d\d\d\d\-\d?\d\-\d?\d/
    :day
  when /\d\d\d\d\-\d?\d/
    :month
  when /\d\d\d\d/
    :year
  else
    raise ArgumentError, "Unacceptable date string #{date_string}"
  end
end

.end_date(en) ⇒ Object



58
59
60
61
# File 'lib/daru/date_time/index.rb', line 58

def end_date en
  en.is_a?(String) ? date_time_from(
    en, determine_date_precision_of(en)) : en
end

.find_date_string_bounds(date_string) ⇒ Object



122
123
124
125
126
# File 'lib/daru/date_time/index.rb', line 122

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



116
117
118
119
120
# File 'lib/daru/date_time/index.rb', line 116

def find_index_of_date data, date_time
  searched = data.bsearch { |d| d[0] >= date_time }
  (!searched.nil? and searched[0] == date_time) ? searched[1] : 
    raise(ArgumentError, "Cannot find #{date_time}")
end

.generate_bounds(date_time, date_precision) ⇒ Object



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/daru/date_time/index.rb', line 160

def generate_bounds date_time, date_precision
  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



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/daru/date_time/index.rb', line 72

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 |i|
      data << new_date
      new_date = offset + new_date
    end
  end

  data
end

.infer_offset(data) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/daru/date_time/index.rb', line 99

def infer_offset data
  possible_freq = data[1] - data[0]
  inferred = true
  data.each_cons(2) do |d|  
    if d[1] - d[0] != possible_freq
      inferred = false
      break
    end
  end

  if inferred
    TIME_INTERVALS[possible_freq].new 
  else
    nil
  end
end

.key_out_of_bounds?(key, data) ⇒ Boolean

Returns:

  • (Boolean)


203
204
205
206
207
208
209
210
211
212
213
# File 'lib/daru/date_time/index.rb', line 203

def key_out_of_bounds? key, data
  precision = determine_date_precision_of key
  date_time = date_time_from key, precision
  case precision
  when :year
    date_time.year < data[0][0].year or date_time.year > data[-1][0].year
  when :month
    (date_time.year < data[0][0].year and date_time.month < data[0][0].month) or
    (date_time.year > data[-1][0].year and date_time.month > data[-1][0].month)
  end
end

.last_date(data) ⇒ Object



199
200
201
# File 'lib/daru/date_time/index.rb', line 199

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.

Raises:

  • (ArgumentError)


30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/daru/date_time/index.rb', line 30

def offset_from_frequency frequency
  frequency = 'D' if frequency.nil?
  return frequency if frequency.kind_of?(Daru::DateOffset)

  matched = /([0-9]*)(MONTH|YEAR|S|H|MB|ME|M|D|W|YB|YE)/.match(frequency)
  raise ArgumentError, 
    "Invalid frequency string #{frequency}" if matched.nil?

  n             = matched[1] == "" ? 1 : matched[1].to_i
  offset_string = matched[2]
  offset_klass  = OFFSETS_HASH[offset_string]

  raise ArgumentError,
    "Cannont interpret offset #{offset_string}" if offset_klass.nil?

  if offset_string.match(/W/)
    day = Regexp.new(Daru::DAYS_OF_WEEK.keys.join('|')).match(frequency).to_s
    return offset_klass.new(n, weekday: Daru::DAYS_OF_WEEK[day])
  end

  offset_klass.new(n)
end

.possibly_convert_to_date_time(data) ⇒ Object



195
196
197
# File 'lib/daru/date_time/index.rb', line 195

def possibly_convert_to_date_time data
  data[0].is_a?(String) ? data.map! { |e| DateTime.parse(e) } : data
end

.start_date(start) ⇒ Object



53
54
55
56
# File 'lib/daru/date_time/index.rb', line 53

def start_date start
  start.is_a?(String) ? date_time_from(
    start, determine_date_precision_of(start)) : start
end

.verify_start_and_end(start, en) ⇒ Object

Raises:

  • (ArgumentError)


92
93
94
95
96
97
# File 'lib/daru/date_time/index.rb', line 92

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