File: active_support/core_ext/date/calculations.rb

Overview
Module Structure
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: ActiveSupport#1
  module: CoreExtensions#2
  module: Date#3
  module: Calculations#5
has properties
module method: included / 1 #6
method: past? #36
method: today? #41
method: future? #46
method: ago / 1 #52
method: since / 1 #58
alias: in since #61
method: beginning_of_day #64
alias: midnight beginning_of_day #67
alias: at_midnight beginning_of_day #68
alias: at_beginning_of_day beginning_of_day #69
method: end_of_day #72
method: plus_with_duration / 1 #76
method: minus_with_duration / 1 #84
method: advance / 1 #94
method: change / 1 #110
method: months_ago / 1 #119
method: months_since / 1 #124
method: years_ago / 1 #129
method: years_since / 1 #134
method: last_year #138
method: prev_year #144
method: next_year #149
method: last_month #153
method: prev_month #159
method: next_month #164
method: beginning_of_week #169
alias: monday beginning_of_week #174
alias: at_beginning_of_week beginning_of_week #175
method: end_of_week #178
alias: at_end_of_week end_of_week #183
method: next_week / 1 #186
method: beginning_of_month #193
alias: at_beginning_of_month beginning_of_month #196
method: end_of_month #199
alias: at_end_of_month end_of_month #203
method: beginning_of_quarter #206
alias: at_beginning_of_quarter beginning_of_quarter #209
method: end_of_quarter #212
alias: at_end_of_quarter end_of_quarter #215
method: beginning_of_year #218
alias: at_beginning_of_year beginning_of_year #221
method: end_of_year #224
alias: at_end_of_year end_of_year #227
method: yesterday #230
method: tomorrow #235
  module: ClassMethods#18
has properties
method: yesterday #20
method: tomorrow #25
method: current #30

Code

   1  module ActiveSupport #:nodoc:
   2    module CoreExtensions #:nodoc:
   3      module Date #:nodoc:
   4        # Enables the use of time calculations within Date itself
   5        module Calculations
   6          def self.included(base) #:nodoc:
   7            base.extend ClassMethods
   8 
   9            base.instance_eval do
  10              alias_method :plus_without_duration, :+
  11              alias_method :+, :plus_with_duration
  12 
  13              alias_method :minus_without_duration, :-
  14              alias_method :-, :minus_with_duration
  15            end
  16          end
  17 
  18          module ClassMethods
  19            # Returns a new Date representing the date 1 day ago (i.e. yesterday's date).
  20            def yesterday
  21              ::Date.today.yesterday
  22            end
  23 
  24            # Returns a new Date representing the date 1 day after today (i.e. tomorrow's date).
  25            def tomorrow
  26              ::Date.today.tomorrow
  27            end
  28 
  29            # Returns Time.zone.today when config.time_zone is set, otherwise just returns Date.today.
  30            def current
  31              ::Time.zone_default ? ::Time.zone.today : ::Date.today
  32            end
  33          end
  34 
  35          # Tells whether the Date object's date lies in the past
  36          def past?
  37            self < ::Date.current
  38          end
  39 
  40          # Tells whether the Date object's date is today
  41          def today?
  42            self.to_date == ::Date.current # we need the to_date because of DateTime
  43          end
  44 
  45          # Tells whether the Date object's date lies in the future
  46          def future?
  47            self > ::Date.current
  48          end
  49 
  50          # Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00)
  51          # and then subtracts the specified number of seconds
  52          def ago(seconds)
  53            to_time.since(-seconds)
  54          end
  55 
  56          # Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00)
  57          # and then adds the specified number of seconds
  58          def since(seconds)
  59            to_time.since(seconds)
  60          end
  61          alias :in :since
  62 
  63          # Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00)
  64          def beginning_of_day
  65            to_time
  66          end
  67          alias :midnight :beginning_of_day
  68          alias :at_midnight :beginning_of_day
  69          alias :at_beginning_of_day :beginning_of_day
  70 
  71          # Converts Date to a Time (or DateTime if necessary) with the time portion set to the end of the day (23:59:59)
  72          def end_of_day
  73            to_time.end_of_day
  74          end
  75 
  76          def plus_with_duration(other) #:nodoc:
  77            if ActiveSupport::Duration === other
  78              other.since(self)
  79            else
  80              plus_without_duration(other)
  81            end
  82          end
  83 
  84          def minus_with_duration(other) #:nodoc:
  85            if ActiveSupport::Duration === other
  86              plus_with_duration(-other)
  87            else
  88              minus_without_duration(other)
  89            end
  90          end
  91 
  92          # Provides precise Date calculations for years, months, and days.  The +options+ parameter takes a hash with
  93          # any of these keys: <tt>:years</tt>, <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>.
  94          def advance(options)
  95            options = options.dup
  96            d = self
  97            d = d >> options.delete(:years) * 12 if options[:years]
  98            d = d >> options.delete(:months)     if options[:months]
  99            d = d +  options.delete(:weeks) * 7  if options[:weeks]
 100            d = d +  options.delete(:days)       if options[:days]
 101            d
 102          end
 103 
 104          # Returns a new Date where one or more of the elements have been changed according to the +options+ parameter.
 105          #
 106          # Examples:
 107          #
 108          #   Date.new(2007, 5, 12).change(:day => 1)                  # => Date.new(2007, 5, 1)
 109          #   Date.new(2007, 5, 12).change(:year => 2005, :month => 1) # => Date.new(2005, 1, 12)
 110          def change(options)
 111            ::Date.new(
 112              options[:year]  || self.year,
 113              options[:month] || self.month,
 114              options[:day]   || self.day
 115            )
 116          end
 117 
 118          # Returns a new Date/DateTime representing the time a number of specified months ago
 119          def months_ago(months)
 120            advance(:months => -months)
 121          end
 122 
 123          # Returns a new Date/DateTime representing the time a number of specified months in the future
 124          def months_since(months)
 125            advance(:months => months)
 126          end
 127 
 128          # Returns a new Date/DateTime representing the time a number of specified years ago
 129          def years_ago(years)
 130            advance(:years => -years)
 131          end
 132 
 133          # Returns a new Date/DateTime representing the time a number of specified years in the future
 134          def years_since(years)
 135            advance(:years => years)
 136          end
 137 
 138          def last_year # :nodoc:
 139            ActiveSupport::Deprecation.warn("Date#last_year is deprecated and has been removed in Rails 3, please use Date#prev_year instead", caller)
 140            prev_year
 141          end
 142 
 143          # Short-hand for years_ago(1)
 144          def prev_year
 145            years_ago(1)
 146          end unless method_defined?(:prev_year)
 147 
 148          # Short-hand for years_since(1)
 149          def next_year
 150            years_since(1)
 151          end
 152 
 153          def last_month # :nodoc:
 154            ActiveSupport::Deprecation.warn("Date#last_month is deprecated and has been removed in Rails 3, please use Date#prev_month instead", caller)
 155            prev_month
 156          end
 157 
 158          # Short-hand for months_ago(1)
 159          def prev_month
 160            months_ago(1)
 161          end unless method_defined?(:prev_month)
 162 
 163          # Short-hand for months_since(1)
 164          def next_month
 165            months_since(1)
 166          end
 167 
 168          # Returns a new Date/DateTime representing the "start" of this week (i.e, Monday; DateTime objects will have time set to 0:00)
 169          def beginning_of_week
 170            days_to_monday = self.wday!=0 ? self.wday-1 : 6
 171            result = self - days_to_monday
 172            self.acts_like?(:time) ? result.midnight : result
 173          end
 174          alias :monday :beginning_of_week
 175          alias :at_beginning_of_week :beginning_of_week
 176 
 177          # Returns a new Date/DateTime representing the end of this week (Sunday, DateTime objects will have time set to 23:59:59)
 178          def end_of_week
 179            days_to_sunday = self.wday!=0 ? 7-self.wday : 0
 180            result = self + days_to_sunday.days
 181            self.acts_like?(:time) ? result.end_of_day : result
 182          end
 183          alias :at_end_of_week :end_of_week
 184 
 185          # Returns a new Date/DateTime representing the start of the given day in next week (default is Monday).
 186          def next_week(day = :monday)
 187            days_into_week = { :monday => 0, :tuesday => 1, :wednesday => 2, :thursday => 3, :friday => 4, :saturday => 5, :sunday => 6}
 188            result = (self + 7).beginning_of_week + days_into_week[day]
 189            self.acts_like?(:time) ? result.change(:hour => 0) : result
 190          end
 191 
 192          # Returns a new ; DateTime objects will have time set to 0:00DateTime representing the start of the month (1st of the month; DateTime objects will have time set to 0:00)
 193          def beginning_of_month
 194            self.acts_like?(:time) ? change(:day => 1,:hour => 0, :min => 0, :sec => 0) : change(:day => 1)
 195          end
 196          alias :at_beginning_of_month :beginning_of_month
 197 
 198          # Returns a new Date/DateTime representing the end of the month (last day of the month; DateTime objects will have time set to 0:00)
 199          def end_of_month
 200            last_day = ::Time.days_in_month( self.month, self.year )
 201            self.acts_like?(:time) ? change(:day => last_day, :hour => 23, :min => 59, :sec => 59) : change(:day => last_day)
 202          end
 203          alias :at_end_of_month :end_of_month
 204 
 205          # Returns a new Date/DateTime representing the start of the quarter (1st of january, april, july, october; DateTime objects will have time set to 0:00)
 206          def beginning_of_quarter
 207            beginning_of_month.change(:month => [10, 7, 4, 1].detect { |m| m <= self.month })
 208          end
 209          alias :at_beginning_of_quarter :beginning_of_quarter
 210 
 211          # Returns a new Date/DateTime representing the end of the quarter (last day of march, june, september, december; DateTime objects will have time set to 23:59:59)
 212          def end_of_quarter
 213            beginning_of_month.change(:month => [3, 6, 9, 12].detect { |m| m >= self.month }).end_of_month
 214          end
 215          alias :at_end_of_quarter :end_of_quarter
 216 
 217          # Returns a new Date/DateTime representing the start of the year (1st of january; DateTime objects will have time set to 0:00)
 218          def beginning_of_year
 219            self.acts_like?(:time) ? change(:month => 1, :day => 1, :hour => 0, :min => 0, :sec => 0) : change(:month => 1, :day => 1)
 220          end
 221          alias :at_beginning_of_year :beginning_of_year
 222 
 223          # Returns a new Time representing the end of the year (31st of december; DateTime objects will have time set to 23:59:59)
 224          def end_of_year
 225            self.acts_like?(:time) ? change(:month => 12,:day => 31,:hour => 23, :min => 59, :sec => 59) : change(:month => 12, :day => 31)
 226          end
 227          alias :at_end_of_year :end_of_year
 228 
 229          # Convenience method which returns a new Date/DateTime representing the time 1 day ago
 230          def yesterday
 231            self - 1
 232          end
 233 
 234          # Convenience method which returns a new Date/DateTime representing the time 1 day since the instance time
 235          def tomorrow
 236            self + 1
 237          end
 238        end
 239      end
 240    end
 241  end