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"