Ruby Snippet – next day of week given date

First published on Fencore Ltd.’s Posterous page on October 13th, 2010

I needed the ability to work out the date of the next weekday after a given date, e.g. what is the date of the Saturday after the 1st December? The following will do it:

#date_convert.rb
require 'date'
require 'active_support/core_ext'
Date::DATE_FORMATS.merge!({british: "%d/%m/%Y"})
class DateConvert
  # usage:
  # date_of_next( day_name, date) where day_name is a string or symbol representation of a full weekday name, e.g. :saturday
  # and date is either a valid Date object or a string representation of a date
  def date_of_next( day_name, date = Date.today.to_s(:british))
    # Note that config/initializers/date_formats.rb has been created with the following lines:
    # Date::DATE_FORMATS[:british] = "%d/%m/%Y" # => 25/4/2007
    # Date::DATE_FORMATS[:british_long] = "%d %B, %Y" # 25 April 2007
    # Date::DATE_FORMATS[:british_long_ordinal] = lambda { |date| date.strftime("#{ActiveSupport::Inflector.ordinalize(date.day)} %B, #
    # day_name must be a string value representing the full day name (or a token equivalent)
    # date must be a valid Date
    #
    # date_of_next( "saturday") is valid
    # date_of_next( "Saturday") is valid
    # date_of_next( :Saturday) is valid
    # date_of_next( "sat", Date.today) is invalid - invalid day_name
    # date_of_next( :saturday, "2010/11/31")) is invalid - ArgumentError: invalid date
    #
    date = date.to_s(:british) if date.kind_of?(Date)
    which_day = (day_name.downcase.to_s + "?").to_sym
    (1..7).each do |inc|
      begin
        date_object = Date.strptime(date, "%d/%m/%Y")
        return date_object + inc if (date_object + inc).send(which_day)
      rescue
        puts "Enter the day as a string or symbol representation of a full weekday name, e.g. :saturday"
        puts "Enter the date as a string value of the form dd/mm/yyyy"
        return
      end
    end
  end
end

require '/Users/martin/work/utils/date_convert.rb'
describe DateConvert, "#date_of_next" do
  before(:each) do
    @dc = DateConvert.new
  end
  it "returns a date object when given a valid day of the week as a string" do
    @dc.date_of_next("saturday").should be_an_instance_of(Date)
    @dc.date_of_next("Saturday").should be_an_instance_of(Date)
  end
  it "returns a date object when given a valid day of the week as a symbol" do
    @dc.date_of_next(:saturday).should be_an_instance_of(Date)
  end
  it "returns a date object when given a valid day of the week and a valid date as a string" do
    @dc.date_of_next("saturday", "9/11/2010").should be_an_instance_of(Date)
  end
  it "returns a date object when given a valid day of the week and a valid date as a Date object" do
    @dc.date_of_next("saturday", Date.today).should be_an_instance_of(Date)
  end
  it "raises an exception when given a valid day of the week and a invalid date as a string" do
    @dc.date_of_next("saturday", "2010/11/9").should raise_exception()
  end
  it "raises an exception when given a day of the week in invalid format" do
    @dc.date_of_next("sat", "9/11/2010").should raise_exception()
  end
  it "returns a date for next saturday that should be a Saturday" do
    @dc.date_of_next("saturday").should be_a_saturday
  end
  it "returns a date for next sunday that should be a Sunday" do
    @dc.date_of_next("sunday").should be_a_sunday
  end
  it "returns a date for next saturday after '9/11/2010' that should be '13/11/2010'" do
    @dc.date_of_next("saturday", '9/11/2010').to_s(:british).should == '13/11/2010'
  end
end

Hope it helps.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s