Easy way to find the Yesterday's date using Perl modules [duplicate] - perl

I wanna calculate the date a week ago from today with a specific format and put it in to a variable. For example, today is Nov 21st. 2014, and I wanna print out: Last week is 2014-11-14.
I know we can use Date::Calc module, but I don't know how.

Check Time::Piece and Time::Seconds core modules,
use Time::Piece;
use Time::Seconds;
my $t = localtime() - ONE_WEEK;
print $t->ymd;
output
2014-11-14

DateTime version
use DateTime;
my $now = DateTime->now(time_zone => 'local')->subtract(weeks => 1);
print $now->ymd, ' ',$now->hms;
Date::Calc version
Instead of one week you can subtract 7 days using Date::Calc module
use Date::Calc qw(Add_Delta_Days);
my #date = Add_Delta_Days( 2014, 11, 21, -7 );
print join('-', #date);
OUTPUT
2014-11-14

This is very simple using Date::Manip
use Date::Manip;
my $today = ParseDate("today");
my $weeksago = DateCalc($today,"-7d");

Why not just subtract X days from the "mday" field of localtime? This example shows subtracting 60 days from the end of august. I'm not sure who corrects the month but I think I'm getting the right answer...
$ date
Wed Aug 30 14:34:14 DFT 2017
$ perl -MPOSIX -e '#t=localtime time; $t[3] -= 60; print strftime( "%Y/%m/%d", #t), "\n";'
2017/07/01

Related

Perl - date calculation

I'm new in Perl. I want to calculate days (e.g. 5 days) after input.
Steps I need to cover:
1. start_date: 08.12.2015
2. add 5 days
3. end date: ?
My idea is to convert the start date into a timestamp. Then I add 5*84.400 seconds. After that, I want to re-convert the end timestamp.
I read the Time::Local module docs, but I did not understand the logic yet.
Is this the right way to handle date calculations?
You can do it using DateTime and DateTime::Format::Strptime. Like this:
use strict;
use DateTime;
use DateTime::Format::Strptime;
my $strp = DateTime::Format::Strptime->new(
pattern => '%d.%m.%Y'
);
my $date = '08.12.2015';
my $dt = $strp->parse_datetime($date);
printf "%s -> %s\n", $date, $dt->add(days => 5)->strftime("%d.%m.%Y");
Using Time::Piece
#!/usr/bin/env perl
use v5.10;
use Time::Piece;
use Time::Seconds;
my $date_string = '08.12.2015';
my $date_format = '%m.%d.%Y';
my $tp = Time::Piece->strptime( $date_string, $date_format );
$tp += 5 * ONE_DAY;
say $tp->strftime($date_format);
Outputs:
08.17.2015
Or another way, in vanilla perl (no use of packages needed), with help from Unix date:
$ date -d 08/12/2015
Wed, Aug 12, 2015 12:00:00 AM
$ date -d 08/12/2015 +%s
1439352000
$ date -d 08/12/2015 +%s|perl -ne 'print scalar localtime $_ + 5*24*60*60'
Mon Aug 17 00:00:00 2015

How to calculate a date a week ago from today

I wanna calculate the date a week ago from today with a specific format and put it in to a variable. For example, today is Nov 21st. 2014, and I wanna print out: Last week is 2014-11-14.
I know we can use Date::Calc module, but I don't know how.
Check Time::Piece and Time::Seconds core modules,
use Time::Piece;
use Time::Seconds;
my $t = localtime() - ONE_WEEK;
print $t->ymd;
output
2014-11-14
DateTime version
use DateTime;
my $now = DateTime->now(time_zone => 'local')->subtract(weeks => 1);
print $now->ymd, ' ',$now->hms;
Date::Calc version
Instead of one week you can subtract 7 days using Date::Calc module
use Date::Calc qw(Add_Delta_Days);
my #date = Add_Delta_Days( 2014, 11, 21, -7 );
print join('-', #date);
OUTPUT
2014-11-14
This is very simple using Date::Manip
use Date::Manip;
my $today = ParseDate("today");
my $weeksago = DateCalc($today,"-7d");
Why not just subtract X days from the "mday" field of localtime? This example shows subtracting 60 days from the end of august. I'm not sure who corrects the month but I think I'm getting the right answer...
$ date
Wed Aug 30 14:34:14 DFT 2017
$ perl -MPOSIX -e '#t=localtime time; $t[3] -= 60; print strftime( "%Y/%m/%d", #t), "\n";'
2017/07/01

How to go back months in Perl taking account of different days in month?

I was wondering if there is an in-built Perl function that adjusts the date if you take a month from it. E.g. if date is the 31st, it will adjust to be the end of the previous month if it doesn't have 31 days.
I would just change it to 30th easily if it weren't for the months with 31 days next to each other (Dec/Jan, Jul/Aug) and February.
I just want to store the date a certain amount of time away from the current date, e.g.
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$current_date = join("-", (1900+$year), ($mon+1), $mday);
$one_month_ago = join("-", (1900+$year), ($mon), $mday);
$one_year_ago = join("-", (1899+$year), ($mon+1), $mday);
I can deal with the February instance as it only applies to years, but if this was taken on the 31st December 2012 then taking away a month would mean 31st Nov 2012, which of course didn't exist. I thought I would ask if there was a function before complicating things for myself... thanks :)
DateTime is not a built-in module, but once you've installed it, it makes this math trivial:
#!/usr/bin/perl
use strict;
use warnings;
use feature qw( say );
use DateTime;
my $dt = DateTime->now;
say $dt->ymd;
$dt->truncate( to => month );
say $dt->ymd;
$dt->add( days => -1 );
say $dt->ymd;
foreach ( 1 .. 12 ) {
$dt->add( months => -1 );
say $dt->ymd;
}
When I run this today (Aug 29, 2012) I get the following output:
[~] $ perl dt.pl
2012-08-29
2012-08-01
2012-07-31
2012-06-30
2012-05-31
2012-04-30
2012-03-31
2012-02-29
2012-01-31
2011-12-31
2011-11-30
2011-10-31
2011-09-30
2011-08-31
2011-07-31
Others have suggested DateTime, but it's quite large, non-core, and can be slow.
A much simpler solution is to use the builtin localtime and POSIX::mktime functions:
use POSIX qw( mktime );
my #t = localtime $epoch;
$t[4] -= 2; # $t[4] is tm_mon
my $two_months_ago = mktime #t;
The mktime() function specifically handles denormalised values; it will cope with the fact that Janurary minus 2 months is November of the previous year, etc.. It will keep the same second/minute/hour of the day, and the same day of the month.
If you have a chance to install module DateTime. It gives your a lot of perks, when you have deal with dates.
use strict;
use DateTime;
my $epoch = ...;
my $dt = DateTime->from_epoch( epoch => $epoch );
$dt->subract(months => 1);
printf "%s", $dt->datetime();

Find week of a year given the date in mm/dd/yyyy

I am trying to find the week that a date falls in, in a certain year. I have a bunch of files that need to be sorted into folders like "week1-2012" and "week34-2011". I tried searching but a lot of the results aren't really helping because I am currently using perl v5.6.1, super old and I can't download any modules. I also found this link ( How do I calculate the week number given a date?) of interest but was wondering how I would go about getting the day of year and week easily. Was thinking of getting the month, and adding the appropriate amount of days to find out the day in the year. Any help would be appreciated. An example of the year format I am looking for is
//year 2012
S M T W R F S
1 2 3 <-- week #1
4 5 6 7 8 9 10 <-- week #2 //came from the link
//dec year 2011
S M T W T F S
27 28 29 31 <-- week #52 or 53, not to sure the actual week
You can use core modules: POSIX and Time::Local
1.parse your date to (sec, min, hour, mday, month, year)
2.convert your date to seconds (epoch)
3.use function strftime to get week from current date
use strict;
use Time::Local;
use POSIX qw(strftime);
my $date = '08/15/2012';
my ($month, $day, $year) = split '/', $date;
my $epoch = timelocal( 0, 0, 0, $day, $month - 1, $year - 1900 );
my $week = strftime( "%U", localtime( $epoch ) );
printf "Date: %s № Week: %s\n", $date, $week;
OUTPUT
Date: 08/15/2012 № Week: 33
Perl 5.6.1 dates from April 2001. Someone is making your life much harder than it needs to be by not giving you modern tools to use. I suggest it's worth spending some time fixing that problem.
If you had Perl 5.10 or greater, then it would include the Time::Piece module. And your problem would become trivial.
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
use Time::Piece;
my $date = '08/15/2012';
my $dt = Time::Piece->strptime($date, '%m/%d/%Y');
say $dt->strftime('week%W-%Y');
Running it gives:
$ ./week
week33-2012
This counts the week as Mon-Sun, not Sun-Sat.
Here's an alternate solution, using DateTime:
use strict;
use warnings;
use DateTime;
my $dt=DateTime->now(time_zone=>"local");
print $dt->week_number . "\n";
The output is, of course:
33
Edit: Of course you can download modules! If nothing else, you can copy and use the relevant code from DateTime.

Looking for Perl 5.12 code that generates yesterday's date in DDMMYY format

I would like a simple way to get yesterday's date (local time) as a string in a Perl script. Preferably, I would like to do this with no module dependencies, since we have a bare bones Perl 5.12 installation.
So, something like:
my $yesterdays_date=...; # Puts for example '301011' into $yesterdays_date,
# if today is October 31st, 2011
Time::Piece is core:
use Time::Piece;
use Time::Seconds qw(ONE_DAY);
my $yesterday = localtime() - ONE_DAY();
print $yesterday->strftime('%d%m%y'), "\n";
If you're concerned about daylight savings, you can normalize the current time to near noon:
use Time::Piece;
use Time::Seconds qw(ONE_DAY ONE_HOUR);
my $today = localtime;
my $yesterday = $today + ONE_HOUR * ( 12 - $today->hour ) - ONE_DAY;
print $yesterday->strftime("%d%m%y"), "\n";
If you can live with dependencies, then use DateTime:
use DateTime;
print DateTime->now->subtract(days => 1)->strftime('%d%m%y'), "\n";
If you're willing to go with dependencies, DateTime will generally do anything you need.
use strict;
use warnings;
use 5.012;
use DateTime;
say DateTime->now->subtract(days => 1)->strftime('%d%m%y');
Just subtract 24 hours (24 hours * 60 minutes * 60 seconds) from current time and get localtime:
say scalar localtime(time - 60*60*24);
# Sun Oct 30 21:04:30 2011
Note, that localtime returns time in string format only in scalar context.
If you need to generate 'DDMMYY' you can just use data structure returned by list context:
my #tm = localtime(time - 60*60*24);
my $date = sprintf("%02d%02d%2d", $tm[3], $tm[4]+1, $tm[5] + 1900);
# 30102011
You can use the POSIX module thusly:
perl -MPOSIX=strftime -le 'print strftime "%m%d%y",localtime(time-(60*60*24))'