Algorithm to truncate date to beginning of week?

I need to be able to take any date after Jan 1, 1980 and truncate it to
the nearest week.

Example:

Wed Jan 09 17:53:23 -0600 1980 should truncate to Sun Jan 06 00:00:00
-0600 1980

Tue Feb 09 12:29:51 -0600 2010 should truncate to Sun Feb 07 00:00:00
-0600 2010

I’ve tried all sorts of tricks with modulus (% operator) on the integer
representation of time but I can’t get anything to work over a range of
dates.

Anyone have any bright ideas?

My end goal is to always be able to pick the first Sunday at midnight
backwards from a given date. If there is another approach to accomplish
this, please share.

cr

On Feb 9, 2010, at 1:32 PM, Chuck R. wrote:

Anyone have any bright ideas?

require ‘active_support’
=> true

Time.now.beginning_of_week
=> Mon Feb 08 00:00:00 -0500 2010

It also looks like midnight is considered part of the next day not the
previous day as in your example.

Gary W.

On Feb 9, 12:32 pm, Chuck R. [email protected] wrote:

My end goal is to always be able to pick the first Sunday at midnight backwards from a given date. If there is another approach to accomplish this, please share.

Use the logic inherent in Date objects. They can tell you the weekday
(as an integer, 0-based starting at Sunday), and subtraction/addition
work on days.

$ irb -rdate
>> d = Date.today
=> #<Date: 4910473/2,0,2299161>
>> d.to_s
=> "2010-02-09"
>> d-d.wday
=> #<Date: 4910469/2,0,2299161>
>> _.to_s
=> "2010-02-07"

A Date object is just that, a date. If you mean a time, you can
recreate the date using parts of the time.

>> t = Time.now
=> Tue Feb 09 12:54:48 -0600 2010
>> d = Date.new(t.year, t.month, t.day)
=> #<Date: 4910473/2,0,2299161>
>> d.to_s
=> "2010-02-09"

Or if you still need a Time object when you’re done, you can go the
other way as well.

>> t = Time.local(d.year, d.month, d.day)
=> Tue Feb 09 00:00:00 -0600 2010

HTH HAND

On Feb 9, 12:53 pm, Gary W. [email protected] wrote:

It also looks like midnight is considered part of the next day not the previous day as in your example.
No, ActiveSupport just thinks Monday is the beginning of the week.

http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Time/Calculations.html#M001151

On Tue, Feb 9, 2010 at 1:53 PM, Gary W. [email protected] wrote:

It also looks like midnight is considered part of the next day not the previous day as in your example.
No, actually ActiveSupport defines the week to start on Monday, which
is the ISO 8601 definition, not Sunday.

To get the beginning of a Sunday starting week using ActiveSupport,
you could use

Time.now.end_of_week.beginning_of_day

This will get the end of the next Sunday on or after the time in
question, and then adjust to the beginning of the day.

Approaches like Time.now.beginning_of_week - 1.day will fail on
Sundays, you’ll get the previous Sunday instead.


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: Rick DeNatale - Developer - IBM | LinkedIn

On Feb 9, 2010, at 12:58 PM, Yossef M. wrote:

d.to_s
=> “2010-02-09”

d-d.wday
=> #<Date: 4910469/2,0,2299161>

_.to_s
=> “2010-02-07”

Ah! Date#wday is what I needed!

I do need Time objects but it’s easy (as you pointed out) to convert
between them.

Thanks for your insight.

cr

On Feb 9, 2010, at 12:53 PM, Gary W. wrote:

It also looks like midnight is considered part of the next day not the previous day as in your example.
Ooh, all of ActiveSupport for a little date manipulation? Nail, meet
hammer!

Thanks for this suggestion. I’m going to go with using Date#wday to
calculate it though.

cr

On Feb 9, 2010, at 2:22 PM, Chuck R. wrote:

Ooh, all of ActiveSupport for a little date manipulation? Nail, meet hammer!

Of course reinventing the wheel isn’t necessarily a good thing either.

Here is another approach:

require ‘chronic’
=> true

Time.now
=> Tue Feb 09 15:31:25 -0500 2010

Chronic.parse ‘midnight last saturday’
=> Sun Feb 07 00:00:00 -0500 2010

Chronic.parse ‘midnight last saturday’, :now => Date.parse(‘12/25/2010’)
=> Sun Dec 19 00:00:00 -0500 2010