Find monday of first week of the month


#1

Hi,

im pretty new to Ruby and i tried to find out how to calculate the date
for the first monday of the first week of the month (i.e. this would be
2007-01-29 for Feb. 2007)
My approach is to get the weekday of the first day of the month and
calculate back from there. By getting the weekday i can tell how far to
calculate back (if necessary at all). If i’m calcualating back from
janurary, i also have to switch back the year.

So this is what i came out with:

 year = 2007
 month = 2

 # get the weekday of the first day of the month
 first_wd = Date.new(year, month, 1).wday

 # if weekday is sunday
 if first_wd == 0
   date_modifier = - 6

 #if weekday is monday
 elsif first_wd == 1
   date_modifier = 1

 # any other day
 else
   date_modifier = - ( first_wd - 1 )
 end

 #if i have to count back, swith month (and year) back
 if date_modifier < 0
   if month > 1
     month -= 1
   else
     month = 12
     year -= 1
   end
 end

 # get date with calculated modifier
 date_start = Date.new(year, month, date_modifier )

Ok, this works, but it seems pretty complicated to me. Is there a
smarter (and more readable) way to do this? As far as i know Ruby right
now, it’s pretty unusual if an “easy” problem like this needs more than
three lines of code ;).

Thx for any help
Regards
Daniel


#2

You may want to try the chronic library

require ‘chronic’
date_start = Chronic.parse(“Monday of first week of February”)


#3

Daniel L. wrote:

Hi,

im pretty new to Ruby and i tried to find out how to calculate the date
for the first monday of the first week of the month (i.e. this would be
2007-01-29 for Feb. 2007)

The first Monday in February is on January 29th? Hm, wait, I think I
understand what you’re trying to say.

My approach is to get the weekday of the first day of the month and
calculate back from there. By getting the weekday i can tell how far to
calculate back (if necessary at all). If i’m calcualating back from
janurary, i also have to switch back the year.

So this is what i came out with:

require ‘date’

date = Date.new(2007, 2)
p date.strftime("%Y-%m-%d") # 2007-02-01
date -= 1 until date.mday == 1
p date.strftime("%Y-%m-%d") # 2007-01-29

Regards,

Dan


#4

removed_email_address@domain.invalid wrote:

You may want to try the chronic library

require ‘chronic’
date_start = Chronic.parse(“Monday of first week of February”)

Oh, now that is cool. :slight_smile:

Dan


#5

Daniel L. wrote:

So this is what i came out with:

 if date_modifier < 0

Ok, this works, but it seems pretty complicated to me. Is there a
smarter (and more readable) way to do this? As far as i know Ruby right
now, it’s pretty unusual if an “easy” problem like this needs more than
three lines of code ;).

Thx for any help
Regards
Daniel

def first_monday( year, month )
date = Date.new( year, month, 1 )
date - ( date.wday - 1 )
end


#6

On Jan 22, 2007, at 4:05 PM, Daniel B. wrote:

require ‘date’

date = Date.new(2007, 2)
p date.strftime("%Y-%m-%d") # 2007-02-01
date -= 1 until date.mday == 1
p date.strftime("%Y-%m-%d") # 2007-01-29

If you start with a Sunday you will end up with a Monday before
that. Not sure that’s what was intended.

James Edward G. II


#7

On Jan 22, 2007, at 4:25 PM, Daniel L. wrote:

So this is what i came out with:

if date_modifier < 0

Ok, this works, but it seems pretty complicated to me. Is there a
smarter (and more readable) way to do this? As far as i know Ruby
right now, it’s pretty unusual if an “easy” problem like this needs
more than three lines of code ;).

Thx for any help
Regards
Daniel

Your attempt isn’t too far off from the Time#beginning_of_week from
ActiveSupport
# File vendor/rails/activesupport/lib/active_support/core_ext/
time/calculations.rb, line 128
128: def beginning_of_week
129: days_to_monday = self.wday!=0 ? self.wday-1 : 6
130: (self - days_to_monday.days).midnight
131: end

Working just with a Date, that gives you:

feb=Date.new(2007,2,1)
=> #<Date: 4908265/2,0,2299161>

feb.to_s
=> “2007-02-01”

feb -= (feb.wday != 0 ? feb.wday-1 : 6)
=> #<Date: 4908259/2,0,2299161>

feb.to_s
=> “2007-01-29”

What about January 2008?

jan08 = Date.new(2008,1,1)
=> #<Date: 4908933/2,0,2299161>

jan08 -= (jan08.wday !=0 ? jan08.wday-1 : 6)
=> #<Date: 4908931/2,0,2299161>

jan08.to_s
=> “2007-12-31”

You shouldn’t have too much trouble wrapping that up into a nice
little method of your own.

-Rob

Rob B. http://agileconsultingllc.com
removed_email_address@domain.invalid


#8

James Edward G. II wrote:

Not sure that’s what was intended.
Whoops.

date = date.mday == 0 ? date += 1 : date -= 1 until date.mday == 1

Regards,

Dan