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
|
#! perl -slw
use strict;
sub lastSunday {
my $now = time;
$now -= 43200 while scalar localtime($now) !~ m[Sun];
return $now;
}
print scalar localtime( lastSunday() );
| [reply] [d/l] |
|
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
| [reply] [d/l] [select] |
|
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.
| [reply] [d/l] |
|
| [reply] |
|
The scalar value of localtime is explicitly not locale dependent. It is a fixed format, see ctime(3)
| [reply] |
|
|
|
|
| [reply] [d/l] |
|
|
|
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
|
| [reply] |
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.
| [reply] |
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. | [reply] [d/l] |
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?
| [reply] [d/l] |
|
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.
| [reply] [d/l] [select] |
|
| [reply] |
|
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).
| [reply] |
|
|
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? | [reply] |
|
| [reply] |
|
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";
| [reply] [d/l] |
|
|
|
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 | [reply] |
|
| [reply] |
|
| [reply] |
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
| [reply] [d/l] |
|
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 );
| [reply] [d/l] [select] |
|
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.
| [reply] |
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.
| [reply] [d/l] |