[Q] algorithm to truncate date to beginning of week?

Discussion in 'Ruby' started by Chuck Remes, Feb 9, 2010.

  1. Chuck Remes

    Chuck Remes Guest

    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
    Chuck Remes, Feb 9, 2010
    #1
    1. Advertising

  2. Chuck Remes

    Gary Wright Guest

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

    > I need to be able to take any date after Jan 1, 1980 and truncate it =

    to the nearest week.
    >=20
    > Example:
    >=20
    > Wed Jan 09 17:53:23 -0600 1980 should truncate to Sun Jan 06 00:00:00 =

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

    -0600 2010
    >=20
    > 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.=20
    >=20
    > Anyone have any bright ideas?


    >> require 'active_support'

    =3D> true
    >> Time.now.beginning_of_week

    =3D> Mon Feb 08 00:00:00 -0500 2010
    >>=20


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

    Gary Wright
    Gary Wright, Feb 9, 2010
    #2
    1. Advertising

  3. Re: algorithm to truncate date to beginning of week?

    On Feb 9, 12:32=A0pm, Chuck Remes <> wrote:
    > My end goal is to always be able to pick the first Sunday at midnight bac=

    kwards 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 =3D Date.today

    =3D> #<Date: 4910473/2,0,2299161>
    >> d.to_s

    =3D> "2010-02-09"
    >> d-d.wday

    =3D> #<Date: 4910469/2,0,2299161>
    >> _.to_s

    =3D> "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 =3D Time.now

    =3D> Tue Feb 09 12:54:48 -0600 2010
    >> d =3D Date.new(t.year, t.month, t.day)

    =3D> #<Date: 4910473/2,0,2299161>
    >> d.to_s

    =3D> "2010-02-09"

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

    >> t =3D Time.local(d.year, d.month, d.day)

    =3D> Tue Feb 09 00:00:00 -0600 2010


    HTH HAND

    --
    -yossef
    Yossef Mendelssohn, Feb 9, 2010
    #3
  4. Re: algorithm to truncate date to beginning of week?

    On Feb 9, 12:53=A0pm, Gary Wright <> wrote:
    > On Feb 9, 2010, at 1:32 PM, Chuck Remes wrote:
    > > Anyone have any bright ideas?
    > >> require 'active_support'

    > =3D> true
    > >> Time.now.beginning_of_week

    >
    > =3D> Mon Feb 08 00:00:00 -0500 2010
    >
    >
    >
    > It also looks like midnight is considered part of the next day not the pr=

    evious day as in your example.

    No, ActiveSupport just thinks Monday is the beginning of the week.

    http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Time/Calcul=
    ations.html#M001151

    --
    -yossef
    Yossef Mendelssohn, Feb 9, 2010
    #4
  5. On Tue, Feb 9, 2010 at 1:53 PM, Gary Wright <> wrote:
    >
    > On Feb 9, 2010, at 1:32 PM, Chuck Remes wrote:
    >
    >> 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?

    >
    >>> 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.


    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: http://www.linkedin.com/in/rickdenatale
    Rick DeNatale, Feb 9, 2010
    #5
  6. Chuck Remes

    Chuck Remes Guest

    Re: algorithm to truncate date to beginning of week?

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

    > On Feb 9, 12:32 pm, Chuck Remes <> 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"


    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
    Chuck Remes, Feb 9, 2010
    #6
  7. Chuck Remes

    Chuck Remes Guest

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

    >
    > On Feb 9, 2010, at 1:32 PM, Chuck Remes wrote:
    >
    >> 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?

    >
    >>> 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.


    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
    Chuck Remes, Feb 9, 2010
    #7
  8. Chuck Remes

    Gary Wright Guest

    On Feb 9, 2010, at 2:22 PM, Chuck Remes wrote:
    >=20
    > 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'

    =3D> true
    >> Time.now

    =3D> Tue Feb 09 15:31:25 -0500 2010
    >> Chronic.parse 'midnight last saturday'

    =3D> Sun Feb 07 00:00:00 -0500 2010
    >> Chronic.parse 'midnight last saturday', :now =3D> =

    Date.parse('12/25/2010')
    =3D> Sun Dec 19 00:00:00 -0500 2010
    Gary Wright, Feb 9, 2010
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Matt
    Replies:
    1
    Views:
    564
    Matthew Speed
    Nov 8, 2003
  2. Matt
    Replies:
    2
    Views:
    491
    Pete Becker
    Nov 8, 2003
  3. Matt
    Replies:
    3
    Views:
    690
    Richard Heathfield
    Nov 8, 2003
  4. Replies:
    1
    Views:
    397
    Marc 'BlackJack' Rintsch
    May 5, 2008
  5. Matt
    Replies:
    11
    Views:
    382
    Aaron Bertrand [MVP]
    Nov 8, 2003
Loading...

Share This Page