Class: TimeRange

Inherits:
Range
  • Object
show all
Defined in:
lib/timerange.rb

Constant Summary collapse

VERSION =
"0.0.2"

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(b = nil, e = Time.now, exclude_end = false, options = {}) ⇒ TimeRange



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/timerange.rb', line 10

def initialize(b = nil, e = Time.now, exclude_end = false, options = {})
  if b.is_a?(Range)
    b, e, exclude_end = b.begin, b.end, b.exclude_end?
  end

  if b.is_a?(Hash)
    options, b, e, exclude_end = b, nil, nil, false
  elsif e.is_a?(Hash)
    options, e, exclude_end = e, nil, false
  end

  time_zone = options[:time_zone] || self.class.time_zone || Time.zone || "Etc/UTC"
  if time_zone.is_a?(ActiveSupport::TimeZone) or (time_zone = ActiveSupport::TimeZone[time_zone])
    # do nothing
  else
    raise "Unrecognized time zone"
  end
  b = time_zone.parse(b) if b.is_a?(String)
  e = time_zone.parse(e) if e.is_a?(String)
  if options[:time_zone]
    b = b.in_time_zone(b)
    e = e.in_time_zone(e)
  end

  if options[:duration]
    e = b + options[:duration]
    exclude_end = true
  end

  super(b, e, exclude_end)
end

Class Method Details

.bucket(period, time, options = {}) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/timerange.rb', line 75

def self.bucket(period, time, options = {})
  time_zone = options[:time_zone] || Time.zone
  day_start = options[:day_start] || 0
  week_start = options[:week_start] || 6

  week_start = [:mon, :tue, :wed, :thu, :fri, :sat, :sun].index((options[:week_start] || :sun).to_sym)
  if !week_start
    raise "Unrecognized :week_start option"
  end

  time = time.to_time.in_time_zone(time_zone) - day_start.hours

  period = period.to_sym
  time =
    case period
    when :second
      time.change(usec: 0)
    when :minute
      time.change(sec: 0)
    when :hour
      time.change(min: 0)
    when :day
      time.beginning_of_day
    when :week
      # same logic as MySQL group
      weekday = (time.wday - 1) % 7
      (time - ((7 - week_start + weekday) % 7).days).midnight
    when :month
      time.beginning_of_month
    when :year
      time.beginning_of_year
    else
      raise "Invalid period"
    end

  time + day_start.hours
end

.todayObject



113
114
115
116
# File 'lib/timerange.rb', line 113

def self.today
  date = Date.today
  new(date, date).expand(:day)
end

.yesterdayObject



118
119
120
121
# File 'lib/timerange.rb', line 118

def self.yesterday
  date = Date.yesterday
  new(date, date).expand(:day)
end

Instance Method Details

#+(period) ⇒ Object



123
124
125
# File 'lib/timerange.rb', line 123

def +(period)
  self.class.new(self.begin + period, self.end + period, exclude_end?)
end

#-(period) ⇒ Object



127
128
129
# File 'lib/timerange.rb', line 127

def -(period)
  self.class.new(self.begin - period, self.end - period, exclude_end?)
end

#bucket(period, time, options = {}) ⇒ Object



71
72
73
# File 'lib/timerange.rb', line 71

def bucket(period, time, options = {})
  self.class.bucket(period, time, options)
end

#expand(period, options = {}) ⇒ Object



55
56
57
58
59
60
61
62
63
# File 'lib/timerange.rb', line 55

def expand(period, options = {})
  e =
    if exclude_end? and self.end == bucket(period, self.end, options)
      self.end
    else
      bucket(period, self.end + 1.send(period), options)
    end
  self.class.new(bucket(period, self.begin, options), e, true)
end

#expand_start(period, options = {}) ⇒ Object



65
66
67
68
69
# File 'lib/timerange.rb', line 65

def expand_start(period, options = {})
  e = self.end
  e = e.in_time_zone(options[:time_zone]) if options[:time_zone]
  self.class.new(bucket(period, self.begin, options), e, exclude_end?)
end

#step(period, options = {}) {|arr.last| ... } ⇒ Object

should step expand by default? TODO return enum

Yields:

  • (arr.last)


44
45
46
47
48
49
50
51
52
53
# File 'lib/timerange.rb', line 44

def step(period, options = {}, &block)
  period = period.is_a?(Symbol) || period.is_a?(String) ? 1.send(period) : period
  arr = [self.begin]
  yield(arr.last) if block_given?
  while v = arr.last + period and cover?(v)
    yield(v) if block_given?
    arr << v
  end
  arr
end