Substract 15 Minutes from time using Perl - perl

I thought this was going to be very simple but I am really out of options now. I want to substract 15 minutes from a given time.
Example
My time is 15:04 I want to substract 15 minutes to be 14:49. I have searched for solutions on the internet but there is no perl module that can help me out.

You can use DateTime:
my $dt = DateTime->new(
year => 1,
month => 1,
day => 1,
hour => 15,
minute => 4,
);
$dt->subtract(minutes => 15);
printf "%d:%d\n", $dt->hour, $dt->minute; # prints 14:49

Well it all depends on how your time is stored. I prefer to use a time_t as returned by the time built in.
my $now = time();
my $before1 = $now - (15*60); # 15 minutes ago
my $before2 = $now - (3*60*60); # 3 hours ago
my $before3 = $now - (2*24*60*60); # 2 days ago
For output I use the POSIX module
print POSIX::strftime( '%Y-%m-%d %T', localtime($before1) );

perl -MClass::Date -e 'my $d=Class::Date->new("2011-07-13 15:04:00"); my $d2 = $d-"15m"; print $d2, "\n";'
Output:
2011-07-13 14:49:00

Try using Date::Calc
use Date::Calc qw(Add_Delta_DHMS);
($year2, $month2, $day2, $h2, $m2, $s2) =
Add_Delta_DHMS( $year, $month, $day, $hour, $minute, $second, $days_offset, $hour_offset, $minute_offset, $second_offset );
($y,$m,$d,$H,$M,$S) = Add_Delta_DHMS(Today_and_Now(), 0, 0, -15, 0);

convert the time to unix time, for example the current time: $unixtime = time(); then subtract 15*60 from it then convert to a nice string with something like
sub display_time {
my ($sec,$min,$hour,$mday,$mon,$year,undef,undef,undef) = localtime(time);
$year += 1900;
$mon += 1;
return "$year.".sprintf("%02d.%02d %02d:%02d:%02d",$mon,$mday,$hour,$min,$sec);
}

You can use the below sub-routine if you are only concerned about time not date:
sub subTime{
my ($time) = #_;
my #splittime = split(':', $time);
my $hour = $splittime[0];
my $min = $splittime[1];
if($min < 15){
$min=($min+60)-15;
$hour-=1;
}
else{
$min = $min-15;
}
return "$hour:$min";
}
Disclamer: This was the solution OP used, he mentioned it in comments in above answer (in #eugene's answer).

Related

Calculating date time in perl

am new to perl am trying to do a script which can check
last seen / days / hours and minutes
i have made some try.
but i need help to make it function well
#!/usr/bin/perl
use DateTime;
my $Datetime = DateTime->now;
my $date = $Datetime->ymd;
my $time = $Datetime->hms;
$Seen_time = "11:50:02";
$Seen_day = "2022-01-12";
if ($Seen_time eq $time) {
print "His Online\n";
}
elsif ($Seen_time ne $time) {
# calculate how many minutes has passed from current time and seen time
print "He was online 3 minutes or hours back\n";
}
elsif ($Seen_day) {
# calculate days from date
print "he was online 2 days back\n";
}
else {
print "we are going to moon soon\n";
}
Here is a very rough implementation using DateTime::Format::Human::Duration
https://metacpan.org/pod/DateTime::Format::Human::Duration
as Håkon Hægland suggested, you will need to fine tune the output:
#!/usr/bin/perl
use DateTime;
use warnings;
use strict;
use diagnostics;
use DateTime::Duration;
use DateTime::Format::Human::Duration;
my $Datetime = DateTime->now;
my $Seen_time = "11:50:02";
my $Seen_day = "2022-01-12";
# You probably need to take the above and get it in a DateTime object this is just for the example:
my $seen = DateTime->new(year => 2022, day => 12, month => 1, hour => 11, minute => 50, second => 2);
#you could use the DateTime->compare method to compare two DateTime objects. The semantics are compatible with Perl's sort function;
#it returns -1 if $seen < $Datetime etc.
my $cmp = DateTime->compare( $seen, $Datetime );
if (!$cmp) {
print "He is Online\n";
}
elsif ($cmp == -1) {
my $d = DateTime::Duration->new();
my $span = DateTime::Format::Human::Duration->new();
my $dur = $Datetime - $seen;
# You can fine tune this output to just me hours or whatever:
print "He was online " . $span->format_duration($dur) . " ago \n";
}
else {
print "We are going to moon soon\n";
}

PERL : I take mday value from locatime as below , . How can I subtract 1 from mday which I take from localtime

PERL : I take mday value from locatime as below ,now I want value of day before yesterday . How can I subtract 1 from mday which I take from localtime
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
my $part = "P".$mday;
print "Today value is $part \n";
my $part_yes = "P".$mday - $num;
print "$part_yes \n";
Using DateTime:
my $dt =
DateTime
->now( time_zone => 'local' )
->set_time_zone('floating') # Do this when working with dates.
->truncate( to => 'days' ); # Optional.
$dt->subtract( days => 2 );
my $yesterday = $dt->day;
DateTime is pretty heavy, and it seems people asking date-time questions invariably come back and say "core modules only!", so here's a solution using only core modules.
use Time::Local qw( timegm );
# Create an timestamp with the same date in UTC as the one local one.
my $epoch = timegm(0, 0, 0, ( localtime() )[3,4,5]);
# We can now do date arithmetic without having to worry about DST switches.
$epoch -= 2 * 24*60*60;
my $yesterday = ( gmtime($epoch) )[3] + 1;
my $now = time(); # time as seconds since 1970-01-01
my $day_ago = $now - 24*60*60;
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($day_ago);
my $part = "P".$mday;
WARNING (ikegami comment): Not all days have 24 hours. This can produce a result that's 0, 1 or 2 days earlier
https://perldoc.perl.org/functions/time
https://perldoc.perl.org/functions/localtime

Determining the time at which a date starts

Say I want to create a daily planner, and I want to divide the day into 15 minute chunks.
Easy, right? Just start at midnight, and... Wrong! In America/Sao_Paulo, one day each year starts at 01:00 because of Daylight Saving Time changes.
Given a time zone and a date, how does one find the epoch time at which the day starts?
My first thought was to use the following, but it assumes each day has a 23:59. That's probably no better of an assumption than assuming each day has a midnight.
perl -MDateTime -E'
say
DateTime->new( year => 2013, month => 10, day => 20 )
->subtract( days => 1 )
->set( hour => 23, minute => 59 )
->set_time_zone("America/Sao_Paulo")
->add( minutes => 1 )
->strftime("%H:%M");
'
01:00
Is there a more robust or more direct alternative?
You'd think this is something that needs to be done commonly! I suspect there's a lot of buggy code out there...
Here's a solution that's coded with the intention of trying to get it incorporated into DateTime.
use strict;
use warnings;
use DateTime qw( );
use DateTime::TimeZone qw( );
# Assumption:
# There is no dt to which one can add time
# to obtain a dt with an earlier date.
sub day_start {
my $tz = shift;
my $dt = shift;
my $local_rd_days = ( $dt->local_rd_values() )[0];
my $seconds = $local_rd_days * 24*60*60;
my $min_idx;
if ( $seconds < $tz->max_span->[DateTime::TimeZone::LOCAL_END] ) {
$min_idx = 0;
} else {
$min_idx = #{ $tz->{spans} };
$tz->_generate_spans_until_match( $dt->utc_year()+1, $seconds, 'local' );
}
my $max_idx = $#{ $tz->{spans} };
my $utc_rd_days;
my $utc_rd_secs;
while (1) {
my $current_idx = int( ( $min_idx + $max_idx )/2 );
my $current = $tz->{spans}[$current_idx];
if ( $seconds < $current->[DateTime::TimeZone::LOCAL_START] ) {
$max_idx = $current_idx - 1;
}
elsif ( $seconds >= $current->[DateTime::TimeZone::LOCAL_END] ) {
$min_idx = $current_idx + 1;
}
else {
my $offset = $current->[DateTime::TimeZone::OFFSET];
# In case of overlaps, always prefer earlier span.
if ($current->[DateTime::TimeZone::IS_DST] && $current_idx) {
my $prev = $tz->{spans}[$current_idx-1];
$offset = $prev->[DateTime::TimeZone::OFFSET]
if $seconds >= $prev->[DateTime::TimeZone::LOCAL_START]
&& $seconds < $prev->[DateTime::TimeZone::LOCAL_END];
}
$utc_rd_days = $local_rd_days;
$utc_rd_secs = -$offset;
DateTime->_normalize_tai_seconds($utc_rd_days, $utc_rd_secs);
last;
}
if ($min_idx > $max_idx) {
$current_idx = $min_idx;
$current = $tz->{spans}[$current_idx];
if (int( $current->[DateTime::TimeZone::LOCAL_START] / (24*60*60) ) != $local_rd_days) {
my $err = 'Invalid local time for date';
$err .= " in time zone: " . $tz->name;
$err .= "\n";
die $err;
}
$utc_rd_secs = $current->[DateTime::TimeZone::UTC_START] % (24*60*60);
$utc_rd_days = int( $current->[DateTime::TimeZone::UTC_START] / (24*60*60) );
last;
}
}
my ($year, $month, $day) = DateTime->_rd2ymd($utc_rd_days);
my ($hour, $minute, $second) = DateTime->_seconds_as_components($utc_rd_secs);
return
$dt
->_new_from_self(
year => $year,
month => $month,
day => $day,
hour => $hour,
minute => $minute,
second => $second,
time_zone => 'UTC',
)
->set_time_zone($tz);
}
Test:
sub new_date {
my $y = shift;
my $m = shift;
my $d = shift;
return DateTime->new(
year => $y, month => $m, day => $d,
#_,
hour => 0, minute => 0, second => 0, nanosecond => 0,
time_zone => 'floating'
);
}
{
# No midnight.
my $tz = DateTime::TimeZone->new( name => 'America/Sao_Paulo' );
my $dt = day_start($tz, new_date(2013, 10, 20));
print($dt->iso8601(), "\n"); # 2013-10-20T01:00:00
$dt->subtract( seconds => 1 );
print($dt->iso8601(), "\n"); # 2013-10-19T23:59:59
}
{
# Two midnights.
my $tz = DateTime::TimeZone->new( name => 'America/Havana' );
my $dt = day_start($tz, new_date(2013, 11, 3));
print($dt->iso8601(), "\n"); # 2013-11-03T00:00:00
$dt->subtract( seconds => 1 );
print($dt->iso8601(), "\n"); # 2013-11-02T23:59:59
}
A practical example,
sub today_as_floating {
return
DateTime
->now( #_ )
->set_time_zone('floating')
->truncate( to => 'day' );
}
{
my $tz = DateTime::TimeZone->new( name => 'local' );
my $dt = today_as_floating( time_zone => $tz );
$dt = day_start($tz, $dt);
print($dt->iso8601(), "\n");
}
A reasonable approach would be to start at 12:00 PM (noon) on that day, and work backwards incrementally until the date changed. The same going forward to find the end of the day.
Noon is appropriate, because (AFAIK) all time zones that have DST changes transition in the middle of the night, to minimize the impact on human beings. Presumably, the vast majority of people are awake during the day, so governments would be foolish to set DST changes during business hours.
You would want to move in 15 minute increments to cover all bases. There are some time zones with :30 or :45 minute offsets, and some that only change by 30 minutes for DST.
Now if you are going back into antiquity, this isn't the best solution because many time zones had adjustments for other reasons than DST - such as initial synchronization with UTC, which could be by some odd minutes or seconds value. So this should work fine with reasonably present dates, but not for all past dates.
If you want something that is less linear, then the algorithm would have to determine the interval of the boundaries for the time zone rule that the date fell into, then use those to check if they fall on the day in question or not. In the source code for Datetime::TimeZone, I see that it defines an internal concept of a "span". You could use DateTime::TimeZone->_span_for_datetime to find the span that the date in question fell into, and then check the start and end dates from there.
I am not a Perl programmer, so I'll leave that exercise to you or someone else. Besides, I checked and the values in the span don't appear to be unix timestamps, so I'm not quite sure how to take it from there - and they appear to be undocumented/internal so I don't think that's necessarily a good idea in Perl anyway.
Time::Local's timelocal() function is clever enough to do the right thing here if you ask for the epoch time for midnight. For 2014, DST changes are as follows:
$ zdump -v America/Sao_Paulo | fgrep 2014
America/Sao_Paulo Sun Feb 16 01:59:59 2014 UTC = Sat Feb 15 23:59:59 2014 BRST isdst=1 gmtoff=-7200
America/Sao_Paulo Sun Feb 16 02:00:00 2014 UTC = Sat Feb 15 23:00:00 2014 BRT isdst=0 gmtoff=-10800
America/Sao_Paulo Sun Oct 19 02:59:59 2014 UTC = Sat Oct 18 23:59:59 2014 BRT isdst=0 gmtoff=-10800
America/Sao_Paulo Sun Oct 19 03:00:00 2014 UTC = Sun Oct 19 01:00:00 2014 BRST isdst=1 gmtoff=-7200
So midnight is "missing" on 2014-10-19. However, if we actually ask for the epoch time for that anyway, and then convert it back into a local time:
$ TZ=America/Sao_Paulo perl -MTime::Local -E 'say scalar localtime(timelocal(0, 0, 0, 19, 9, 114))'
Sun Oct 19 01:00:00 2014
And one second before:
$ TZ=America/Sao_Paulo perl -MTime::Local -E 'say scalar localtime(timelocal(0, 0, 0, 19, 9, 114)-1)'
Sat Oct 18 23:59:59 2014
[This functionality is now available from DateTimeX::Start]
Here's a solution using only DT's public methods:
sub day_start {
my ($y, $m, $d, $tz) = #_;
$tz = DateTime::TimeZone->new( name => $tz )
if !ref($tz);
my $dt = DateTime->new( year => $y, month => $m, day => $d );
my $target_day = ( $dt->utc_rd_values )[0];
my $min_epoch = int($dt->epoch()/60) - 24*60;
my $max_epoch = int($dt->epoch()/60) + 24*60;
while ($max_epoch > $min_epoch) {
my $epoch = ( $min_epoch + $max_epoch ) >> 1;
$dt = DateTime->from_epoch( epoch => $epoch*60, time_zone => $tz );
if (( $dt->local_rd_values )[0] < $target_day) {
$min_epoch = $epoch;
} else {
$max_epoch = $epoch;
}
}
return DateTime->from_epoch(epoch => $max_epoch*60, time_zone => $tz);
}
Since most dates do have a midnight, a check should be added at the top to bypass the search when it's not needed.
Assumptions:
There is no dt to which one can add time to obtain a dt with an earlier date.
In no time zone does a date starts more than 24*60*60 seconds before the date starts in UTC.
In no time zone does a date starts more than 24*60*60 seconds after the date starts in UTC.
Jumps in time zones only occur on times with zero seconds. (Optimization)
Test:
{
# No midnight.
my $tz = DateTime::TimeZone->new( name => 'America/Sao_Paulo' );
my $dt = day_start(2013, 10, 20, $tz);
print($dt->epoch, " ", $dt->iso8601, "\n"); # 1382238000 2013-10-20T01:00:00
$dt->subtract( seconds => 1 );
print($dt->epoch, " ", $dt->iso8601, "\n"); # 1382237999 2013-10-19T23:59:59
}
{
# Two midnights.
my $tz = DateTime::TimeZone->new( name => 'America/Havana' );
my $dt = day_start(2013, 11, 3, $tz);
print($dt->epoch, " ", $dt->iso8601, "\n"); # 1383451200 2013-11-03T00:00:00
$dt->subtract( seconds => 1 );
print($dt->epoch, " ", $dt->iso8601, "\n"); # 1383451199 2013-11-02T23:59:59
}
One (cumbersome) possible solution: figure out a conservative time (say, 23:00:00 or 23:50:00--the only important part is that no date past or future should roll over before this time), and then increment that time until the date changes:
#Assume $year/$month/$day contain the date one day prior to the target date
my $dt = DateTime->new(
time_zone => $tz,
year => $year,
month => $month,
day => $day,
hour => 23,
minute => 59,
second => 0,
);
while($dt->year == $year && $dt->month == $month && $dt->day == $day) {
$dt->add(seconds => 1);
}
#At this point $dt should, if I understand the functioning of DateTime correctly, contain the earliest "valid" time in the target date.
I'm 100% sure there is a better solution to this; the ideal would be if DateTime defaulted to the earliest valid time for a given time zone, given a date with no time--currently it defaults to zero for all of those values, and I'm not certain that it will correct the value if it's not valid for that TZ. If it does internally correct those values, then that solution would be vastly preferable; it might be worth contacting the maintainer of DateTime to see what the actual behaviour is, and if said behaviour is guaranteed in the future if it is currently the desired behaviour.
You can use DateTime::TimeZone directly to query for a valid local time. DateTime::TimeZone raises an exception if the local time does not exist due to a nearby offset change.
use DateTime;
use DateTime::TimeZone;
my $zone = DateTime::TimeZone->new(name => 'America/Sao_Paulo');
my $dt = DateTime->new(year => 2013, month => 10, day => 20);
sub valid_local_time {
eval { $zone->offset_for_local_datetime($dt) };
return $# !~ /^Invalid local time/;
}
while (!valid_local_time()) {
$dt->add(minutes => 15);
}
$dt->set_time_zone($zone);
sub local_time_lt {
my ($x, $y) = #_;
return $x->local_rd_as_seconds < $y->local_rd_as_seconds;
}
sub local_time_eq {
my ($x, $y) = #_;
return $x->local_rd_as_seconds == $y->local_rd_as_seconds;
}
my $copy = $dt->clone->subtract(seconds => 1);
if (local_time_lt($dt, $copy)) {
my $delta = $copy->local_rd_as_seconds - $dt->local_rd_as_seconds;
local_time_eq($dt, $copy->subtract(seconds => $delta))
or die qq/Could not determine start of day ($dt [${\$zone->name}])/;
$dt = $copy;
}
print $dt->strftime('%H:%M'), "\n";
Is everyone missing the really obvious way to do it? It's midnight on the current day. I.e. set the seconds, minutes and hours to zero, and take the mday, mon and year fields from localtime.
use POSIX qw( mktime tzset );
$ENV{TZ} = 'America/Sao_Paulo';
tzset();
my $epoch = mktime( 0, 0, 0, 20, 10-1, 2013-1900 );
print localtime($epoch)."\n"; # Sun Oct 20 01:00:00 2013

In Perl, how can I find last Thursday's date? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
In Perl, how can find the date of the previous Monday for a given date?
In the perl, how to write a function to get last Thursday's date? Today (11/21), I want to get 11/17. How can I figure out if a given date is a Sunday or not?
Seems like a work for DateTime (which is the module usually recommended to manipulate dates in Perl). This small example should answer both your questions:
use strict;
use warnings;
use DateTime;
my $d = DateTime->now;
while ( $d->day_of_week != 4 ) {
$d->subtract( days => 1 );
}
print $d->ymd;
Other posts use DateTime too, but they have issues this post addresses.
use DateTime qw( );
my $dt = DateTime->today( time_zone => 'local' );
$dt->subtract( days => ($dt->day_of_week - 4) % 7 );
say $dt->ymd(''); # 20111117
Issues addressed:
Uses the local date instead of the date in or near England.
Uses today instead of now since you're only dealing with dates.
Avoids needless loops.
Note:
Returns the current date is today is a Thursday. You accepted an answer that did the same, so I presume that's what you want.
Update: The above can fail on certain days for certain time zones. (Not all days have a midnight!) Solution:
use DateTime qw( );
my $dt = DateTime->now( time_zone => 'local' );
$dt->set_time_zone('floating');
$dt->truncate( to => 'days' );
$dt->subtract( days => ($dt->day_of_week - 4) % 7 );
say $dt->ymd(''); # 20111117
I'd use what larsen wrote, although reading the localtime reference won't hurt you. You could do something like this to check if its Sunday:
($second, $minute, $hour, $dayOfMonth, $month, $yearOffset,
$dayOfWeek, $dayOfYear, $daylightSavings) = localtime();
if ($dayOfWeek == 0) print("Don't go to work!");
If all you wanted to test was the day-of-the-week an array slice of the localtime() works nicely:
print q(Today is Sunday) if ((localtime)[6]==0)
You can also use Date::Calc:
How do I calculate the last and the next Saturday for any given date?
use Date::Calc qw( Today Day_of_Week Add_Delta_Days
Day_of_Week_to_Text Date_to_Text );
$searching_dow = 6; # 6 = Saturday
#today = Today();
$current_dow = Day_of_Week(#today);
if ($searching_dow == $current_dow)
{
#prev = Add_Delta_Days(#today,-7);
#next = Add_Delta_Days(#today,+7);
}
else
{
if ($searching_dow > $current_dow)
{
#next = Add_Delta_Days(#today,
$searching_dow - $current_dow);
#prev = Add_Delta_Days(#next,-7);
}
else
{
#prev = Add_Delta_Days(#today,
$searching_dow - $current_dow);
#next = Add_Delta_Days(#prev,+7);
}
}
$dow = Day_of_Week_to_Text($searching_dow);
print "Today is: ", ' ' x length($dow),
Date_to_Text(#today), "\n";
print "Last $dow was: ", Date_to_Text(#prev), "\n";
print "Next $dow will be: ", Date_to_Text(#next), "\n";
use Date::Calc qw(:all);
($week, $year) = Week_of_Year(Today());# Week_of_Year(2011,11,21);
print Date_to_Text(Add_Delta_Days(Monday_of_Week($week - 1,$year),3));#THU - MON = 3
#output:Thu 17-Nov-2011
#isSunday?
Day_of_Week(2011,11,20) == 7 # 7 is Sunday enum code(from 1 : Monday)
With just localtime and the POSIX base module, you can do this:
my #ltime = localtime();
my $t
= POSIX::mktime(( 0 ) x 3
, $ltime[3] - ( 7 - 4 + $ltime[6] )
, #ltime[4,5]
);
This will always give you the last Thursday before the last Sunday. So if the day is Saturday, it will give you the previous week's Thursday, but if it's Sunday, it will give you the last past Thursday.
If you prefer the last past Thursday computation, you might do this:
my $t
= POSIX::mktime(( 0 ) x 3
, $ltime[3] - $ltime[6] + ( $ltime[6] > 4 ? 4 : -3 )
, #ltime[4,5]
);
Date::Simple has a pretty clean interface.
#!/usr/bin/perl
use strict;
use warnings;
use Date::Simple qw/ today /;
my $d = today;
# If today is already Thurs, subtract 1 before searching for prior Thursday.
# If today is Thurs and you want to capture that (and not Thur a week ago),
# don't subtract the 1 from $d.
$d--;
$d-- while $d->day_of_week != 4;
print $d->strftime("%Y%m%d");

How can I get this week's dates in Perl?

I have the following loop to calculate the dates of the current week and print them out. It works, but I am swimming in the amount of date/time possibilities in Perl and want to get your opinion on whether there is a better way. Here's the code I've written:
#!/usr/bin/env perl
use warnings;
use strict;
use DateTime;
# Calculate numeric value of today and the
# target day (Monday = 1, Sunday = 7); the
# target, in this case, is Monday, since that's
# when I want the week to start
my $today_dt = DateTime->now;
my $today = $today_dt->day_of_week;
my $target = 1;
# Create DateTime copies to act as the "bookends"
# for the date range
my ($start, $end) = ($today_dt->clone(), $today_dt->clone());
if ($today == $target)
{
# If today is the target, "start" is already set;
# we simply need to set the end date
$end->add( days => 6 );
}
else
{
# Otherwise, we calculate the Monday preceeding today
# and the Sunday following today
my $delta = ($target - $today + 7) % 7;
$start->add( days => $delta - 7 );
$end->add( days => $delta - 1 );
}
# I clone the DateTime object again because, for some reason,
# I'm wary of using $start directly...
my $cur_date = $start->clone();
while ($cur_date <= $end)
{
my $date_ymd = $cur_date->ymd;
print "$date_ymd\n";
$cur_date->add( days => 1 );
}
As mentioned, this works, but is it the quickest or most efficient? I'm guessing that quickness and efficiency may not necessarily go together, but your feedback is very appreciated.
A slightly improved version of friedo's answer ...
my $start_of_week =
DateTime->today()
->truncate( to => 'week' );
for ( 0..6 ) {
print $start_of_week->clone()->add( days => $_ );
}
However, this assumes that Monday is the first day of the week. For Sunday, start with ...
my $start_of_week =
DateTime->today()
->truncate( to => 'week' )
->subtract( days => 1 );
Either way, it's better to use the truncate method than re-implement it, as friedo did ;)
You can use the DateTime object to get the current day of the week as a number ( 1-7 ). Then just use that to find the current week's Monday. For example:
my $today = DateTime->now;
my $start = $today->clone;
# move $start to Monday
$start->subtract( days => ( $today->wday - 1 ) ); # Monday gives 1, so on monday we
# subtract zero.
my $end = $start->clone->add( days => 7 );
The above is untested but the idea should work.
Would this work:
use strict;
use warnings;
use POSIX qw<strftime>;
my ( $day, $pmon, $pyear, $wday ) = ( localtime )[3..6];
$day -= $wday - 1; # Get monday
for my $d ( map { $day + $_ } 0..6 ) {
print strftime( '%A, %B %d, %Y', ( 0 ) x 3, $d, $pmon, $pyear ), "\n";
}
I'm printing them only as an illustration. You could store them as timestamps, like this:
use POSIX qw<mktime>;
my #week = map { mktime(( 0 ) x 3, $day + $_, $pmon, $pyear ) } 0..6;
This should work:
use POSIX; # for strftime
my $time = time ();
my $seconds = 24*60*60;
my #time = gmtime ();
$time = $time - $time[6] * $seconds;
for my $wday (0..6) {
$time += $seconds;
my #wday = gmtime ($time);
print strftime ("%A %d %B %Y\n", #wday);
}
Gives me:
$ ./week.pl
Monday 24 May 2010
Tuesday 25 May 2010
Wednesday 26 May 2010
Thursday 27 May 2010
Friday 28 May 2010
Saturday 29 May 2010
Sunday 30 May 2010
If you want to get weeks starting on Sunday, change $time[6] to ($time[6] + 1).
This assumes you want the GMT weeks. Change gmtime to localtime to get local time zone weeks.