Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Is there an easy way to get the start date of the current week?

by ramjamman (Sexton)
on Aug 21, 2010 at 12:31 UTC ( [id://856442]=perlquestion: print w/replies, xml ) Need Help??

ramjamman has asked for the wisdom of the Perl Monks concerning the following question:

I need to get the date of the Sunday of current week for a search query.

Just wondering if there is a easy way rather than get today and if today is monday/tuesday wednesday etc minus 1 2 3 days etc

Had thought of getting the week number and getting the start date from that

Would welcome any suggestions Thank You
  • Comment on Is there an easy way to get the start date of the current week?

Replies are listed 'Best First'.
Re: Is there an easy way to get the start date of the current week?
by BrowserUk (Patriarch) on Aug 21, 2010 at 13:01 UTC

    One way:

    #! perl -slw use strict; sub lastSunday { my $now = time; $now -= 43200 while scalar localtime($now) !~ m[Sun]; return $now; } print scalar localtime( lastSunday() );

      I just wrote another message in which I mention rarely using the components from list-context localtime(), except to feed into strftime(). This is one of those rare situations which call for using the components. In scalar context, localtime() gives you a fully formatted date-time string, but in list context it returns:

      my ( $seconds, $minutes, $hours, $day_of_month, $month_idx, $years_since_1900, $day_of_week_number, $day_of_year, $id_dst ) = localtime($now);
      So rather than generating a date string "Sat Aug 21 22:00:53 2010" and then parsing it with a regex ( not even substr()! .. shocking! ), why not use the day of the week component .... 0 == Sunday through to 6 == Saturday.
      $now -= 43200 while (localtime($now))[6]; # count back half days till +Sunday

      --
      TTTATCGGTCGTTATATAGATGTTTGCA

        So rather than generating a date string "Sat Aug 21 22:00:53 2010" and then parsing it with a regex ( not even substr()! .. shocking! ), why not use the day of the week component

        How many times do you need to calculate 'last sunday' in any given run of a program?

        I think that if you are doing it more than once, you've programmed an error. Even if the run transitions midnight, using two different definitions of that term within a single run of the program, is likely to be an inconsistency with ramifications.

        On that basis, you should only calculate it once. And so the performance gain of only taking 3 milliseconds over 6 is neither here nor there.

        Even if you do the sensible thing and (having obtained the day of week) perform a calculation rather than a loop:

        sub lastSunday2 { my $now = time; my @now = localtime $now; return $now -= ( $now[ 6 ] * 2 - 1 ) * 43200; }

        And so cut the cost of that single call to 1 millisecond, you're still never going to notice it.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

      This can break in two ways:

      1. In a locale where "Sun" is not Sunday
      2. If Monday is the first day of the week, in which case you will have to go forward (for the question asked). You've chosen your sub name to be clear that you're going backward though.

      Enjoy, Have FUN! H.Merijn
        The scalar value of localtime is explicitly not locale dependent. It is a fixed format, see ctime(3)
        In a locale where "Sun" is not Sunday

        But then the routine would not be called lastSunday() either...

Re: Is there an easy way to get the start date of the current week?
by roboticus (Chancellor) on Aug 21, 2010 at 12:43 UTC
Re: Is there an easy way to get the start date of the current week?
by dasgar (Priest) on Aug 21, 2010 at 13:28 UTC

    You could use Date::Calc. If you go that route, you might want to use Week_of_Year, Monday_of_Week and Add_Delta_Days functions.

    I haven't tested BrowserUK's suggestion, but that looks like less work than going this route.

Re: Is there an easy way to get the start date of the current week?
by ramjamman (Sexton) on Aug 21, 2010 at 16:11 UTC
    Thank You ikegami exactly what I was looking for with just a line added to format the result to a date only.
    my $dt = DateTime->today(); my $dow = $dt->day_of_week(); $dt->subtract( days => $dow % 7 ); $dt = $dt->date();

    Has been an interesting afternoon and the support from all monks very much appreciated as each answer helps improve my old brain to think perl again.

Re: Is there an easy way to get the start date of the current week?
by ramjamman (Sexton) on Aug 21, 2010 at 13:23 UTC

    Thanks for your replies! roboticus I had already looked at the DateTime module on CPAN but nothing stood out other than determining the week of the year and then getting the Sunday date from that as being an easy way.

    BrowserUk thanks that works fine! Just would be interested if you could breakdown the line

    $now -= 43200 while scalar localtime($now) !~ m[Sun];

    Into what is actually being done here which will help me understand exactly how the answer is acheived.

    I did think after I had posted the easy way would be to take date now and just changed the day to Sunday. Could this be what you are doing?
      Basically, yes, it subtracts half a day (43200 seconds) from $now until the stringification of localtime($now) ($now represented as a string like 'Sat Aug 21 06:33:51 2010') contains 'Sun' for Sunday.
      Keep in mind there are two hours every year where that code won't work (due to DST). Not every day has 24 hours. There is a solution below that doesn't suffer from this problem.

      Update: Ah, he's only subbing 12 hours!

        Care to point out which hours that would be? Unless there's a timezone that skips 12 hours or more on DST, I don't see there's a problem. Had ramjamman actually suggested to subtract 86400 in each iteration, there would be 6 hours/year where this would be a problem - the hour between midnight and 1 AM on the Monday - Saturday following the Sunday when DST is enabled. (Assuming DST skips an hour, and starts on a Sunday. And assuming the local timezone actually has DST - many parts of the world don't).
Re: Is there an easy way to get the start date of the current week?
by james2vegas (Chaplain) on Aug 21, 2010 at 13:56 UTC
    The problem with basing it off week numbers is that week numbers are based on weeks starting on Monday, not Sunday, so you would need to check that your start date is not already a Sunday before continuing.

    Is this purely an intellectual exercise or is there a reason you don't just subtract the right number of days from your start date to get the beginning of the week?
      is there a reason you don't just subtract the right number of days from your start date to get the beginning of the week?

      Care to demonstrate that given an arbitrary date?

        Sure.
        Update: changed hour to noon, instead of midnight, thanks daylight saving time (now works for the week of March 14 2010, thanks ikegami)
        use strict; use warnings; use Time::Piece; use Time::Seconds; use Date::Calc qw(Mktime); sub get_bofw { my $time = Mktime ( @_ ); my $t = localtime($time); my $bow = $t - ($t->_wday * ONE_DAY); } my $bofw = get_bofw( 2010, 03, 16, 12, 0, 0 ); print "$bofw\n";
Re: Is there an easy way to get the start date of the current week?
by ramjamman (Sexton) on Aug 21, 2010 at 14:21 UTC
    Is this purely an intellectual exercise or is there a reason you don't just subtract the right number of days from your start date to get the beginning of the week?

    It is required to be able to run a report which is querying a mysql database for records of a particular week. Not a problem if the report is run on say a Monday it would return the required info but if say it was run on a Wednesday it would contain part of the current week and part of the following week using mysql's interval week.

    EG: xxxxx AND `s_date` >= DATE_SUB( CURDATE( ) , INTERVAL 8 WEEK ) AND `s_date` < DATE_SUB( CURDATE( ) , INTERVAL 7 WEEK ) So I need to replace CURDATE( ) with the date of the Sunday of the week the report is being run preferably in the format YYYY-MM-DD

      ramjamman:

      In this case (querying a database), I'd suggest doing the date manipulation in SQL rather than perl.

      ...roboticus

Re: Is there an easy way to get the start date of the current week?
by ramjamman (Sexton) on Aug 21, 2010 at 15:13 UTC

    Yes looking at the MySql that would work nicely I guess. However it would still be nice to do it in perl so the variable can be used as a title in the report ie report for week beginning xxx

    I have found an answer that could be adapted for my request at http://datetime.perl.org/index.cgi?FAQSampleCalculations Thanks everyone for your input

    # The date and target (1 is Monday, 7 Sunday) my $dt = DateTime->new(year => 1998, month => 4, day => 3); # Friday my $target = 6; # Saturday # Get the day of the week for the given date my $dow = $dt->day_of_week(); # Apply the corrections my ($prev, $next) = ($dt->clone(), $dt->clone()); if ($dow == $target) { $prev->add( days => -7 ); $next->add( days => 7 ); } else { my $correction = ( $target - $dow + 7 ) % 7; $prev->add( days => $correction - 7 ); $next->add( days => $correction ); } # $prev is 1998-03-28, $next is 1998-04-04

      It doesn't find the current week — it finds the week before and after a reference date — and it's more elaborate than necessary.

      For Sunday,

      my $dt = DateTime->today(); my $dow = $dt->day_of_week(); $dt->substract( days => $dow % 7 );

      For Monday,

      my $dt = DateTime->today(); my $dow = $dt->day_of_week(); $dt->substract( days => ( $dow + 6 ) % 7 );

      If I'm already using MySQL, I usually don't bother trying to calculate dates with in the code. You can use MySQL to calculate the date in your query and return the date value along with the other query results. Alternatively, you can call MySQL first with a query that does nothing more than calculate the desired date, then use that result in report headings and later queries.

      Just saying, there's always more than one way to a solution.

Re: Is there an easy way to get the start date of the current week?
by ambrus (Abbot) on Sep 23, 2014 at 15:53 UTC

    I tried to find a nice solution to this with Date::Manip, but I couldn't. There probably is a nicer solution, so please tell me. Anyway, this should work, I hope, even if it's ugly:

    use warnings; use Date::Manip 6.30; my $today = Date::Manip::Date->new(q(today)); my $sunday = $today->new($today->calc($today->new_delta("+1day")) ->printf("%G-W%W-1"))->calc($today->new_delta("-1day")); say $today->printf("today: %Y-%m-%d %A\n"), $sunday->printf("Sunday: % +Y-%m-%d %A");"

    The complicated date formula calculates the Sunday of this week. It's complicated because you seem to want to work with weeks starting with Sundays, whereas I only know how to ask Date::Manip to work with week starting with Mondays.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://856442]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (3)
As of 2024-04-20 01:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found