ruby Date extensions

I recently cooked these up, thought someone else might find them handy. Now you can say date.first_of_month, date.first_of_year, etc.


module DateExtensions
  def first_of_week
    self - self.wday
  end

  def first_of_month
    self - self.day+1
  end

  def first_of_quarter
    (self << (self.month%3 - 1 )%3) - self.day+1
  end

  def first_of_year
    (self << self.month-1) - self.day+1  
  end
end
Date.send :include, DateExtensions

Addendum: oops, looks like there are already similar methods in Rails’ ActiveSupport:

beginning_of_* rather than first_of_*

However, begining_of_week assumes Monday is the first day of the week, while my version assumes Sunday is the first day.

Here are my tests:

require File.dirname(__FILE__) + '/../test_helper'

class DateExtensionsTest < Test::Rails::TestCase

  def test_first_of_week
    day = Date.new( 2008, 1, 1 )
    w   = day.first_of_week
    # sunday is first day of week
    assert_equal 0, w.wday
    assert_equal 30, w.day
  end

  def test_first_of_month
    day = Date.new( 2008, 1, 15 )
    assert_equal 1, day.first_of_month.day
  end

  def test_first_of_year
    day = Date.new( 2008, 5, 27 )
    y   = day.first_of_year
    assert_equal 1, y.month
    assert_equal 1, y.day
  end

  def test_first_of_quarter_q1    
    [1,2,3].each do |month|
      day = Date.new( 2008, month, 13 )
      q   = day.first_of_quarter
      assert_equal 1, q.day
      assert_equal 1, q.month
    end
  end

  def test_first_of_quarter_q2
    [4,5,6].each do |month|
      day = Date.new( 2008, month, 13 )
      q   = day.first_of_quarter
      assert_equal 1, q.day
      assert_equal 4, q.month
    end
  end

  def test_first_of_quarter_q3
    [7,8,9].each do |month|
      day = Date.new( 2008, month, 13 )
      q   = day.first_of_quarter
      assert_equal 1, q.day
      assert_equal 7, q.month
    end
  end

  def test_first_of_quarter_q4
    [10,11,12].each do |month|
      day = Date.new( 2008, month, 13 )
      q   = day.first_of_quarter
      assert_equal 1, q.day
      assert_equal 10, q.month
    end    
  end

end

Sorry, comments are closed for this article.