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