How do I get yesterday's date in perl?

旧街凉风 提交于 2020-07-05 10:15:14

问题


Currently i take today date using below.I need to get yesterday date using this.. how can i get that ?

my $today = `date "+%Y-%m-%d"`;

回答1:


If you want yesterday's date:

use DateTime qw( );

my $yday_date =
   DateTime
      ->now( time_zone => 'local' )
      ->set_time_zone('floating')
      ->truncate( to => 'days' )
      ->subtract( days => 1 )
      ->strftime('%Y-%m-%d');

For example, in New York, at 2019-05-14 01:00:00, it will give 2019-05-13.

For example, in New York, at 2019-11-04 00:00:00, it will give 2019-11-03.

Note that ->now( time_zone => 'local' )->set_time_zone('floating')->truncate( to => 'days' ) is used instead of ->today( time_zone => 'local' ) to solve 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, at 2019-05-14 01:00:00, it will give 2019-05-13 01:00:00.

For example, in New York, at 2019-03-10 12:00:00, it will give 2019-03-09 12:00:00.

For example, in New York, at 2019-03-11 02:30:00, it will give an error. (2019-03-10 02:30:00 doesn'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, at 2019-05-14 01:00:00, it will give 2019-05-13 01:00:00.

For example, in New York, at 2019-03-10 12:00:00, it will give 2019-03-09 11:00:00.

For example, in New York, at 2019-03-11 02:30:00, it will give 2019-03-10 01:30:00.




回答2:


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).




回答3:


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;



回答4:


With Time::Moment, for just yesterday's date:

use strict;
use warnings;
use Time::Moment;
my $yesterday = Time::Moment->now->minus_days(1)->strftime('%Y-%m-%d');

Time::Moment works in instants and offsets, not time zones, so if you want the exact date and time of "one day ago" in your local time zone as in the DateTime examples, you can use Time::Moment::Role::TimeZone.

use strict;
use warnings;
use Time::Moment;
use Role::Tiny ();
my $class = Role::Tiny->create_class_with_roles('Time::Moment', 'Time::Moment::Role::TimeZone');
my $yesterday = $class->now->minus_days(1)->with_system_offset_same_local; # 1 day ago
my $yesterday = $class->now->minus_days(1)->with_system_offset_same_instant; # 24 hours ago

And the same caveats apply if the current time does not exist in the previous day in the local time zone.




回答5:


my $yesterday = `date -d yesterday +%Y%m%d-%H%M%S`;



回答6:


Using the backtick string has some quirks.... I generally disklike that operator.

Let me recommand the use of localtime() function provided by Time::Piece module (there is a bulitin localtime() function, but the one from Time::Piece is awesomer :)


use Time::Piece;

my ($t, $today, $yesterday);

$t = localtime();
$today = sprintf('%04d/%02d/%02d', $t->year, $t->mon, $t->mday);

$t = localtime(time() - 86400);
$yesterday = sprintf('%04d/%02d/%02d', $t->year, $t->mon, $t->mday);



来源:https://stackoverflow.com/questions/56122365/how-do-i-get-yesterdays-date-in-perl

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!