Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #8571: refactoring_and_adding_yesterday_and_tomorrow_constructors.diff

File refactoring_and_adding_yesterday_and_tomorrow_constructors.diff, 12.6 kB (added by gbuesing, 2 years ago)
  • test/core_ext/date_ext_test.rb

    old new  
    126126  def test_last_month_on_31st 
    127127    assert_equal Date.new(2004, 2, 29), Date.new(2004, 3, 31).last_month 
    128128  end   
     129 
     130  def test_yesterday_constructor 
     131    assert_equal Date.today - 1, Date.yesterday 
     132  end 
     133   
     134  def test_tomorrow_constructor 
     135    assert_equal Date.today + 1, Date.tomorrow 
     136  end 
    129137end 
  • lib/active_support/core_ext/date/calculations.rb

    old new  
    44      # Enables the use of time calculations within Time itself 
    55      module Calculations 
    66        def self.included(base) #:nodoc: 
    7           base.send(:include, ClassMethods) 
     7          base.send(:extend, ClassMethods) 
    88           
    99          base.send(:alias_method, :plus_without_duration, :+) 
    1010          base.send(:alias_method, :+, :plus_with_duration) 
     
    1414        end 
    1515 
    1616        module ClassMethods 
    17           def plus_with_duration(other) #:nodoc: 
    18             if ActiveSupport::Duration === other 
    19               other.since(self) 
    20             else 
    21               plus_without_duration(other) 
    22             end 
     17          def yesterday 
     18            ::Date.today.yesterday 
    2319          end 
    2420           
    25           def minus_with_duration(other) #:nodoc: 
    26             if ActiveSupport::Duration === other 
    27               plus_with_duration(-other) 
    28             else 
    29               minus_without_duration(other) 
    30             end 
     21          def tomorrow 
     22            ::Date.today.tomorrow 
    3123          end 
    32            
    33           # Provides precise Date calculations for years, months, and days.  The +options+ parameter takes a hash with  
    34           # any of these keys: :months, :days, :years. 
    35           def advance(options) 
    36             d = ::Date.new(year + (options.delete(:years) || 0), month, day) 
    37             d = d >> options.delete(:months) if options[:months] 
    38             d = d + options.delete(:days) if options[:days] 
    39             d 
     24        end 
     25         
     26        def plus_with_duration(other) #:nodoc: 
     27          if ActiveSupport::Duration === other 
     28            other.since(self) 
     29          else 
     30            plus_without_duration(other) 
    4031          end 
    41  
    42           # Returns a new Date where one or more of the elements have been changed according to the +options+ parameter. 
    43           # 
    44           # Examples: 
    45           # 
    46           #   Date.new(2007, 5, 12).change(:day => 1)                  # => Date.new(2007, 5, 12) 
    47           #   Date.new(2007, 5, 12).change(:year => 2005, :month => 1) # => Date.new(2005, 1, 12) 
    48           def change(options) 
    49             ::Date.new( 
    50               options[:year]  || self.year, 
    51               options[:month] || self.month, 
    52               options[:day]   || options[:mday] || self.day # mday is deprecated 
    53             ) 
     32        end 
     33         
     34        def minus_with_duration(other) #:nodoc: 
     35          if ActiveSupport::Duration === other 
     36            plus_with_duration(-other) 
     37          else 
     38            minus_without_duration(other) 
    5439          end 
    55            
    56           # Returns a new Date/DateTime representing the time a number of specified months ago 
    57           def months_ago(months) 
    58             months_since(-months) 
    59           end 
     40        end 
     41         
     42        # Provides precise Date calculations for years, months, and days.  The +options+ parameter takes a hash with  
     43        # any of these keys: :months, :days, :years. 
     44        def advance(options) 
     45          d = ::Date.new(year + (options.delete(:years) || 0), month, day) 
     46          d = d >> options.delete(:months) if options[:months] 
     47          d = d + options.delete(:days) if options[:days] 
     48          d 
     49        end 
    6050 
    61           def months_since(months) 
    62             year, month, day = self.year, self.month, self.day 
     51        # Returns a new Date where one or more of the elements have been changed according to the +options+ parameter. 
     52        # 
     53        # Examples: 
     54        # 
     55        #   Date.new(2007, 5, 12).change(:day => 1)                  # => Date.new(2007, 5, 12) 
     56        #   Date.new(2007, 5, 12).change(:year => 2005, :month => 1) # => Date.new(2005, 1, 12) 
     57        def change(options) 
     58          ::Date.new( 
     59            options[:year]  || self.year, 
     60            options[:month] || self.month, 
     61            options[:day]   || options[:mday] || self.day # mday is deprecated 
     62          ) 
     63        end 
     64         
     65        # Returns a new Date/DateTime representing the time a number of specified months ago 
     66        def months_ago(months) 
     67          months_since(-months) 
     68        end 
    6369 
    64             month += months 
     70        def months_since(months) 
     71          year, month, day = self.year, self.month, self.day 
    6572 
    66             # in case months is negative 
    67             while month < 1 
    68              month += 12 
    69              year -= 1 
    70             end 
     73          month += months 
    7174 
    72             # in case months is positive 
    73             while month > 12 
    74              month -= 12 
    75              year += 1 
    76             end 
    77  
    78             max = ::Time.days_in_month(month, year) 
    79             day = max if day > max 
    80  
    81             change(:year => year, :month => month, :day => day) 
     75          # in case months is negative 
     76          while month < 1 
     77           month += 12 
     78           year -= 1 
    8279          end 
    8380 
    84           # Returns a new Date/DateTime representing the time a number of specified years ago 
    85           def years_ago(years) 
    86             change(:year => self.year - years) 
     81          # in case months is positive 
     82          while month > 12 
     83           month -= 12 
     84           year += 1 
    8785          end 
    8886 
    89           def years_since(years) 
    90             change(:year => self.year + years) 
    91           end 
     87          max = ::Time.days_in_month(month, year) 
     88          day = max if day > max 
    9289 
    93           # Short-hand for years_ago(1) 
    94           def last_year 
    95             years_ago(1) 
    96           end 
     90          change(:year => year, :month => month, :day => day) 
     91        end 
    9792 
    98           # Short-hand for years_since(1) 
    99           def next_year 
    100             years_since(1
    101           end 
     93        # Returns a new Date/DateTime representing the time a number of specified years ago 
     94        def years_ago(years) 
     95          change(:year => self.year - years
     96        end 
    10297 
    103           # Short-hand for months_ago(1) 
    104           def last_month 
    105             months_ago(1) 
    106           end 
     98        def years_since(years) 
     99          change(:year => self.year + years) 
     100        end 
    107101 
    108           # Short-hand for months_since(1) 
    109           def next_month 
    110             months_since(1) 
    111           end 
     102        # Short-hand for years_ago(1) 
     103        def last_year 
     104          years_ago(1) 
     105        end 
    112106 
    113           # Returns a new Date/DateTime representing the "start" of this week (i.e, Monday; DateTime objects will have time set to 0:00) 
    114           def beginning_of_week 
    115             days_to_monday = self.wday!=0 ? self.wday-1 : 6 
    116             result = self - days_to_monday 
    117             self.acts_like?(:time) ? result.midnight : result 
    118           end 
    119           alias :monday :beginning_of_week 
    120           alias :at_beginning_of_week :beginning_of_week 
     107        # Short-hand for years_since(1) 
     108        def next_year 
     109          years_since(1) 
     110        end 
    121111 
    122           # Returns a new Date/DateTime representing the start of the given day in next week (default is Monday). 
    123           def next_week(day = :monday) 
    124             days_into_week = { :monday => 0, :tuesday => 1, :wednesday => 2, :thursday => 3, :friday => 4, :saturday => 5, :sunday => 6} 
    125             result = (self + 7).beginning_of_week + days_into_week[day] 
    126             self.acts_like?(:time) ? result.change(:hour => 0) : result 
    127           end           
     112        # Short-hand for months_ago(1) 
     113        def last_month 
     114          months_ago(1) 
     115        end 
    128116 
    129           # 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) 
    130           def beginning_of_month 
    131             self.acts_like?(:time) ? change(:day => 1,:hour => 0, :min => 0, :sec => 0) : change(:day => 1) 
    132           end 
    133           alias :at_beginning_of_month :beginning_of_month 
     117        # Short-hand for months_since(1) 
     118        def next_month 
     119          months_since(1) 
     120        end 
    134121 
    135           # 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) 
    136           def end_of_month 
    137             last_day = ::Time.days_in_month( self.month, self.year ) 
    138             self.acts_like?(:time) ? change(:day => last_day,:hour => 0, :min => 0, :sec => 0) : change(:day => last_day) 
    139           end 
    140           alias :at_end_of_month :end_of_month 
     122        # Returns a new Date/DateTime representing the "start" of this week (i.e, Monday; DateTime objects will have time set to 0:00) 
     123        def beginning_of_week 
     124          days_to_monday = self.wday!=0 ? self.wday-1 : 6 
     125          result = self - days_to_monday 
     126          self.acts_like?(:time) ? result.midnight : result 
     127        end 
     128        alias :monday :beginning_of_week 
     129        alias :at_beginning_of_week :beginning_of_week 
    141130 
    142           # 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) 
    143           def beginning_of_quarter 
    144             beginning_of_month.change(:month => [10, 7, 4, 1].detect { |m| m <= self.month }) 
    145           end 
    146           alias :at_beginning_of_quarter :beginning_of_quarter 
     131        # Returns a new Date/DateTime representing the start of the given day in next week (default is Monday). 
     132        def next_week(day = :monday) 
     133          days_into_week = { :monday => 0, :tuesday => 1, :wednesday => 2, :thursday => 3, :friday => 4, :saturday => 5, :sunday => 6} 
     134          result = (self + 7).beginning_of_week + days_into_week[day] 
     135          self.acts_like?(:time) ? result.change(:hour => 0) : result 
     136        end           
    147137 
    148           # Returns a new Date/DateTime representing the start of the year (1st of january; DateTime objects will have time set to 0:00) 
    149           def beginning_of_year 
    150             self.acts_like?(:time) ? change(:month => 1, :day => 1, :hour => 0, :min => 0, :sec => 0) : change(:month => 1, :day => 1) 
    151           end 
    152           alias :at_beginning_of_year :beginning_of_year 
     138        # 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) 
     139        def beginning_of_month 
     140          self.acts_like?(:time) ? change(:day => 1,:hour => 0, :min => 0, :sec => 0) : change(:day => 1) 
     141        end 
     142        alias :at_beginning_of_month :beginning_of_month 
    153143 
    154           # Convenience method which returns a new Date/DateTime representing the time 1 day ago 
    155           def yesterday 
    156             self - 1 
    157           end 
     144        # 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) 
     145        def end_of_month 
     146          last_day = ::Time.days_in_month( self.month, self.year ) 
     147          self.acts_like?(:time) ? change(:day => last_day,:hour => 0, :min => 0, :sec => 0) : change(:day => last_day) 
     148        end 
     149        alias :at_end_of_month :end_of_month 
    158150 
    159           # Convenience method which returns a new Date/DateTime representing the time 1 day since the instance time 
    160           def tomorrow 
    161             self + 1 
    162           end 
     151        # 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) 
     152        def beginning_of_quarter 
     153          beginning_of_month.change(:month => [10, 7, 4, 1].detect { |m| m <= self.month }) 
    163154        end 
     155        alias :at_beginning_of_quarter :beginning_of_quarter 
     156 
     157        # Returns a new Date/DateTime representing the start of the year (1st of january; DateTime objects will have time set to 0:00) 
     158        def beginning_of_year 
     159          self.acts_like?(:time) ? change(:month => 1, :day => 1, :hour => 0, :min => 0, :sec => 0) : change(:month => 1, :day => 1) 
     160        end 
     161        alias :at_beginning_of_year :beginning_of_year 
     162 
     163        # Convenience method which returns a new Date/DateTime representing the time 1 day ago 
     164        def yesterday 
     165          self - 1 
     166        end 
     167 
     168        # Convenience method which returns a new Date/DateTime representing the time 1 day since the instance time 
     169        def tomorrow 
     170          self + 1 
     171        end 
    164172      end 
    165173    end 
    166174  end