Perl - How to get the previous Wednesday's date from a specified date without using DateTime

Everything,

I want to know the date of the previous Wednesday from the specified date.

Eg. I have the date "20150804" and I will need "20150729".

DateTime is not available, and I also can not set it.

I looked through a few examples, but they used DateTime.

Can you redirect me to where I can get help? Thanks.

I plan to code something like below.

the code:

#!/opt/perl-5.8.0/bin/perl use warnings; use strict; my $dt="20150804"; my $prevWednesday=getPrevWednesday($dt); sub getPrevWednesday() { my $givenDt=shift; ... } 
+4
source share
4 answers

Another brute force approach, this time using another core module, Time :: Local .

 #!/usr/bin/perl use warnings; use strict; use Time::Local; sub prev_wednesday { my $date = shift; my ($year, $month, $day) = $date =~ /(....)(..)(..)/; my $time = timelocal(0, 0, 12, $day, $month - 1, $year); do { $time -= 60 * 60 * 24 } until (localtime $time)[6] == 3; # <- Wednesday my ($y, $m, $d) = (localtime $time)[5, 4, 3]; return sprintf "%4d%02d%02d\n", 1900 + $y, $m + 1, $d; } print $_, ' ', prev_wednesday($_), for qw( 20150804 20150805 20150806 20150101 20000301 20010301 ); 
+5
source

Brute force is always used.

 #!/usr/bin/perl use strict; use warnings; use 5.010; use POSIX 'strftime'; my $ONE_DAY = 24 * 60 * 60; # Get now my $time = time; # Subtract days until you get to a Wednesday do { $time -= $ONE_DAY; } until (localtime($time))[6] == 3; # Format say strftime '%Y%m%d', localtime $time; 

But if you are working in a Perl environment where you cannot install modules from CPAN, then it is always worth working to remove this restriction. Modern Perl programming is often an example of combining the right series of CPAN modules. If you don’t have access to CPAN, you just make your life a lot harder than it should be.

If you really cannot remove the restriction, then find another job. It is not worth dealing with people who impose such meaningless restrictions.

Update: Just noticed that you are also using a prehistoric version of Perl. You need to remove use 5.010 and replace say with print . And update your resume: - /

Update 2: choroba solution is better. It deals with any date in the correct format. Mine only deals with the current date. Advice on how to fix your work environment is still there.

+2
source

Using Time::Piece :

 use feature qw(say); use strict; use warnings; use Time::Piece; use Time::Seconds; my $str = '20150804'; my $fmt = '%Y%m%d'; my $t = Time::Piece->strptime($str, $fmt); do { $t = $t - ONE_DAY; } until ( $t->day eq 'Wed'); say $t->strftime($fmt); 
+2
source

Here is a more elegant solution that does not use bruteforce.

 use strict; use warnings; use Time::Local 'timelocal'; use POSIX 'strftime'; my $dt = "20150804"; say getPrevWednesday($dt); # note you do not want () here, # see http://perldoc.perl.org/perlsub.html#Prototypes sub getPrevWednesday { my $givenDt = shift; # parse the string into a unix timestamp my ( $year, $month, $day ) = $givenDt =~ /(....)(..)(..)/; my $timestamp = timelocal( 0, 0, 12, $day, $month - 1, $year ); # get the day of week, ignore the rest my ( undef, undef, undef, undef, undef, undef, $wday ) = localtime $timestamp; # because we start the week with Sunday on day 0 # and to get to the previous Wednesday from Sunday it's # 4 days (Wednesday is 3) we can add 4 to the # number of this day, divide by 7, take the leftover (modulo) # and then subtract that many days # (86_400 is one day in seconds) # v- -6 ------ # 6 % 7 = 6 # +4 -----v # v # 0 1 2 3 4 5 6 0 1 2 3 4 5 6 # SMTWTFSSMTWTFS my $prev_wed = $timestamp - ( ( $wday + 4 ) % 7 * 86_400 ); # go one week back if we got the same day $prev_wed -= ( 7 * 86_400 ) if $prev_wed == $timestamp; # debug output warn "in: " . localtime($timestamp) . "\n"; warn "out: " . localtime($prev_wed) . "\n\n"; # put it back into your format return strftime('%Y%m%d', localtime $timestamp); } 

Exit:

 # STDOUT 20150804 # STDERR in: Tue Aug 4 12:00:00 2015 out: Wed Jul 29 12:00:00 2015 
+2
source

All Articles