reporting_period.rb - reportable - Fork of reportable required by WarVox, from hdm/reportable.
(HTM) git clone git://jay.scot/reportable
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
---
reporting_period.rb (6711B)
---
1 module Saulabs
2
3 module Reportable
4
5 # A reporting period is a specific hour or a specific day etc. depending on the used {Saulabs::Reportable::Grouping}.
6 #
7 class ReportingPeriod
8
9 # The actual +DateTime the reporting period represents
10 #
11 attr_reader :date_time
12
13 # The {Saulabs::Reportable::Grouping} of the reporting period
14 #
15 attr_reader :grouping
16
17 # Initializes a new reporting period.
18 #
19 # @param [Saulabs::Reportable::Grouping] grouping
20 # the grouping the generate the reporting period for
21 # @param [DateTime] date_time
22 # the +DateTime+ to generate the reporting period for
23 #
24 def initialize(grouping, date_time = nil)
25 @grouping = grouping
26 @date_time = parse_date_time(date_time || DateTime.now)
27 end
28
29 # Gets a reporting period relative to the current one.
30 #
31 # @param [Fixnum] offset
32 # the offset to get the reporting period for
33 #
34 # @return [Saulabs::Reportable::ReportingPeriod]
35 # the reporting period relative by offset to the current one
36 #
37 # @example Getting the reporting period one week later
38 #
39 # reporting_period = Saulabs::Reportable::ReportingPeriod.new(:week, DateTime.now)
40 # next_week = reporting_period.offset(1)
41 #
42 def offset(offset)
43 self.class.new(@grouping, @date_time + offset.send(@grouping.identifier))
44 end
45
46 # Gets the first reporting period for a grouping and a limit (optionally relative to and end date).
47 #
48 # @param [Saulabs::ReportingPeriod::Grouping] grouping
49 # the grouping to get the first reporting period for
50 # @param [Fixnum] limit
51 # the limit to get the first reporting period for
52 # @param [DateTime] end_date
53 # the end date to get the first reporting period for (the first reporting period is then +end_date+ - +limit+ * +grouping+)
54 #
55 # @return [Saulabs::Reportable::ReportingPeriod]
56 # the first reporting period for the grouping, limit and optionally end date
57 #
58 def self.first(grouping, limit, end_date = nil)
59 self.new(grouping, end_date).offset(-limit)
60 end
61
62 # Gets a reporting period from a DB date string.
63 #
64 # @param [Saulabs::Reportable::Grouping] grouping
65 # the grouping to get the reporting period for
66 # @param [String] db_string
67 # the DB string to parse and get the reporting period for
68 #
69 # @return [Saulabs::Reportable::ReportingPeriod]
70 # the reporting period for the {Saulabs::Reportable::Grouping} as parsed from the db string
71 #
72 def self.from_db_string(grouping, db_string)
73 return self.new(grouping, db_string) if db_string.is_a?(Date) || db_string.is_a?(Time)
74 parts = grouping.date_parts_from_db_string(db_string.to_s)
75 case grouping.identifier
76 when :hour
77 self.new(grouping, DateTime.new(parts[0], parts[1], parts[2], parts[3], 0, 0))
78 when :day
79 self.new(grouping, Date.new(parts[0], parts[1], parts[2]))
80 when :week
81 self.new(grouping, Date.commercial(parts[0], parts[1], 1))
82 when :month
83 self.new(grouping, Date.new(parts[0], parts[1], 1))
84 end
85 end
86
87 # Gets the next reporting period.
88 #
89 # @return [Saulabs::Reportable::ReportingPeriod]
90 # the reporting period after the current one
91 #
92 def next
93 self.offset(1)
94 end
95
96 # Gets the previous reporting period.
97 #
98 # @return [Saulabs::Reportable::ReportingPeriod]
99 # the reporting period before the current one
100 #
101 def previous
102 self.offset(-1)
103 end
104
105 # Gets whether the reporting period +other+ is equal to the current one.
106 #
107 # @param [Saulabs::Reportable::ReportingPeriod] other
108 # the reporting period to check for whether it is equal to the current one
109 #
110 # @return [Boolean]
111 # true if +other+ is equal to the current reporting period, false otherwise
112 #
113 def ==(other)
114 if other.is_a?(Saulabs::Reportable::ReportingPeriod)
115 @date_time == other.date_time && @grouping.identifier == other.grouping.identifier
116 elsif other.is_a?(Time) || other.is_a?(DateTime)
117 @date_time == parse_date_time(other)
118 else
119 raise ArgumentError.new("Can only compare instances of #{self.class.name}")
120 end
121 end
122
123 # Gets whether the reporting period +other+ is smaller to the current one.
124 #
125 # @param [Saulabs::Reportable::ReportingPeriod] other
126 # the reporting period to check for whether it is smaller to the current one
127 #
128 # @return [Boolean]
129 # true if +other+ is smaller to the current reporting period, false otherwise
130 #
131 def <(other)
132 if other.is_a?(Saulabs::Reportable::ReportingPeriod)
133 return @date_time < other.date_time
134 elsif other.is_a?(Time) || other.is_a?(DateTime)
135 @date_time < parse_date_time(other)
136 else
137 raise ArgumentError.new("Can only compare instances of #{self.class.name}")
138 end
139 end
140
141 # Gets the latest point in time that is included the reporting period. The latest point in time included in a reporting period
142 # for grouping hour would be that hour and 59 minutes and 59 seconds.
143 #
144 # @return [DateTime]
145 # the latest point in time that is included in the reporting period
146 #
147 def last_date_time
148 case @grouping.identifier
149 when :hour
150 DateTime.new(@date_time.year, @date_time.month, @date_time.day, @date_time.hour, 59, 59)
151 when :day
152 DateTime.new(@date_time.year, @date_time.month, @date_time.day, 23, 59, 59)
153 when :week
154 date_time = (@date_time - @date_time.wday.days) + 7.days
155 Date.new(date_time.year, date_time.month, date_time.day)
156 when :month
157 Date.new(@date_time.year, @date_time.month, (Date.new(@date_time.year, 12, 31) << (12 - @date_time.month)).day)
158 end
159 end
160
161 private
162
163 def parse_date_time(date_time)
164 case @grouping.identifier
165 when :hour
166 DateTime.new(date_time.year, date_time.month, date_time.day, date_time.hour)
167 when :day
168 date_time.to_date
169 when :week
170 date_time = (date_time - date_time.wday.days) + 1.day
171 Date.new(date_time.year, date_time.month, date_time.day)
172 when :month
173 Date.new(date_time.year, date_time.month, 1)
174 end
175 end
176
177 end
178
179 end
180
181 end