How do I get yesterday's date in perl?
If you want yesterday's date:
use DateTime qw( );
my $yday_date =
DateTime
->now( time_zone => 'local' )
->set_time_zone('floating')
->truncate( to => 'day' )
->subtract( days => 1 )
->strftime('%Y-%m-%d');
For example, in New York on 2019-05-14 at 01:00:00, it would have returned 2019-05-13.
For example, in New York on 2019-11-04 at 00:00:00, it would have returned 2019-11-03.
Note that ->now( time_zone => 'local' )->set_time_zone('floating')->truncate( to => 'day' )
is used instead of ->today( time_zone => 'local' )
to avoid this problem.
If you want the time a day earlier:
use DateTime qw( );
my $yday_datetime =
DateTime
->now( time_zone => 'local' )
->subtract( days => 1 )
->strftime('%Y-%m-%d %H:%M:%S');
For example, in New York on 2019-05-14 at 01:00:00, it would have returned 2019-05-13 01:00:00.
For example, in New York on 2019-03-10 at 12:00:00, it would have returned 2019-03-09 12:00:00.
For example, in New York on 2019-03-11 at 02:30:00, it would have resulted in an error. 2019-03-10 02:30:00 didn't exist because of the switch to Daylight Saving Time.
If you want the time 24 hours earlier:
use DateTime qw( );
my $yday_datetime =
DateTime
->now( time_zone => 'local' )
->subtract( hours => 24 )
->strftime('%Y-%m-%d %H:%M:%S');
For example, in New York on 2019-05-14 at 01:00:00, it would have returned 2019-05-13 01:00:00.
For example, in New York on 2019-03-10 at 12:00:00, it would have returned 2019-03-09 11:00:00.
For example, in New York on 2019-03-11 at 02:30:00, it would have returned 2019-03-10 01:30:00.
Using DateTime module
use strict;
use warnings;
use feature 'say';
use DateTime;
my $today = DateTime->today(time_zone => 'local');
my $yesterday = $today->clone->add(days => -1);
say $yesterday->ymd; #--> 2019-05-13
or directly
my $yesterday = DateTime->today(time_zone => 'local')->add(days => -1);
Now these are objects with which you can do practically anything date-time related.
To extract a string in the question's format use $yesterday->ymd
since ymd's default format is %Y-%m-%d
. Practically arbitrary formats can be obtained using strftime method.
There is no reason to reach for system facilities for a job like this. More to the point, the module is incomparably more sophisticated and rounded, for all kinds of curious cases and needs.
An example: At some date-times, as Daylight Saving Time kicks in, certain time periods just don't exist. The docs offer an example of 2003-04-06, when 01:59:59 "jumps" to 03:00:00 and that hour is gone. The module handles attempts to use such (non-existing times) correctly, by throwing errors.
And if you need to do any work with dates then using system's date
isn't even an option since you get back merely a string, which you'd have to parse by hand for any further use.
It has been added that in fact the time is wanted as well, not only the date. Then, for example
my $today = DateTime->now(time_zone => 'local');
say $today->strftime("%Y%m%d_%H.%M.%S"); #--> 20190522_22.44.23
my $yesterday = $today->clone->add(days => -1);
say $yesterday->strftime("%Y%m%d_%H.%M.%S"); #--> 20190521_22.44.23
where method now "keeps" the (local) time, along with the date (today
is truncate
-ed now
).
I recommend using DateTime (as described in ikegami's answer). But if you don't want to install a CPAN module, this method uses only features available in the standard Perl installation.
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
use Time::Local;
use POSIX 'strftime';
# Get the current date/time
my ($sec, $min, $hr, $day, $mon, $yr) = localtime;
# Get the epoch seconds for midday today
# (we use midday to eliminate potential problems
# when entering or leaving daylight savings time)
my $midday = timelocal(0, 0, 12, $day, $mon, $yr);
# Subtract a day's worth of seconds from the epoch
my $midday_yesterday = $midday - (24 * 60 * 60);
# Convert that epoch value to a string date using
# localtime() and POSIX::strftime().
my $yesterday = strftime('%Y%m%d', localtime($midday_yesterday));
say $yesterday;