Monday, October 26, 2009

Recipe 3.10. Finding the Day of the Week










Recipe 3.10. Finding the Day of the Week





Problem


You want to find the day of the week for a certain date.




Solution


Use the
wday
method (supported by both Time and DateTime) to find the day of the week as a number between 0 and 6. Sunday is day zero.


The following code yields to a code block the date of every Sunday between two dates. It uses
wday
to find the first Sunday following the start date (keeping in mind that the first date may itself be a Sunday). Then it adds seven days at a time to get subsequent Sundays:



def every_sunday(d1, d2)
# You can use 1.day instead of 60*60*24 if you're using Rails.
one_day = d1.is_a?(Time) ? 60*60*24 : 1
sunday = d1 + ((7-d1.wday) % 7) * one_day
while sunday < d2
yield sunday
sunday += one_day * 7
end
end

def print_every_sunday(d1, d2)
every_sunday(d1, d2) { |sunday| puts sunday.strftime("%x")}
end

print_every_sunday(Time.local(2006, 1, 1), Time.local(2006, 2, 4))
# 01/01/06
# 01/08/06
# 01/15/06
# 01/22/06
# 01/29/06





Discussion


The most commonly used parts of a time are its calendar and clock readings: year, day, hour, and so on. Time and DateTime let you access these, but they also give you access to a few other aspects of a time: the Julian
day of the year (yday), and, more usefully, the day of the week (wday).


The every_sunday method will accept either two Time objects or two DateTime objects. The only difference is the number you need to add to an object to increment it by one day. If you're only going to be using one kind of object, you can simplify the code a little.


To get the day of the week as an English string, use the strftime directives %A and %a:



t = Time.local(2006, 1, 1)
t.strftime("%A %A %A!") # => "Sunday Sunday Sunday!"
t.strftime("%a %a %a!") # => "Sun Sun Sun!"



You can find the day of the week and the day of the year, but Ruby has no built-in method for finding the week of the year (there is a method to find the commercial week of the year; see Recipe 3.11). If you need such a method, it's not hard to create one using the day of the year and the day of the week. This code defines a week method in a module, which it mixes in to both Date and Time:



require 'date'
module Week
def week
(yday + 7 - wday) / 7
end
end

class Date
include Week
end

class Time
include Week
end

saturday = DateTime.new(2005, 1, 1)
saturday.week # => 0
(saturday+1).week # => 1 #Sunday, January 2
(saturday-1).week # => 52 #Friday, December 31





See Also


  • Recipe 3.3, "Printing a Date"

  • Recipe 3.5, "Doing Date Arithmetic"

  • Recipe 3.11, "Handling
    Commercial Dates"













No comments: